{
  "canonical_name": "kilhubprojects/memory-mesh",
  "compilation_id": "pack_9b109dd48b024d44ba8c47ea230daa90",
  "created_at": "2026-05-15T05:45:21.442068+00:00",
  "created_by": "project-pack-compiler",
  "feedback": {
    "carrier_selection_notes": [
      "viable_asset_types=mcp_config, recipe, host_instruction, eval, preflight",
      "recommended_asset_types=mcp_config, recipe, host_instruction, eval, preflight"
    ],
    "evidence_delta": {
      "confirmed_claims": [
        "identity_anchor_present",
        "capability_and_host_targets_present",
        "install_path_declared_or_better"
      ],
      "missing_required_fields": [],
      "must_verify_forwarded": [
        "Run or inspect `pip install memorymesh-mcp` in an isolated environment.",
        "Confirm the project exposes the claimed capability to at least one target host."
      ],
      "quickstart_execution_scope": "allowlisted_sandbox_smoke",
      "sandbox_command": "pip install memorymesh-mcp",
      "sandbox_container_image": "python:3.12-slim",
      "sandbox_execution_backend": "docker",
      "sandbox_planner_decision": "deterministic_isolated_install",
      "sandbox_validation_id": "sbx_fb7968669b2e40008700d40ba68e1a14"
    },
    "feedback_event_type": "project_pack_compilation_feedback",
    "learning_candidate_reasons": [],
    "template_gaps": []
  },
  "identity": {
    "canonical_id": "project_9286d7363bae44bd69eb6fc0f662f346",
    "canonical_name": "kilhubprojects/memory-mesh",
    "homepage_url": null,
    "license": "unknown",
    "repo_url": "https://github.com/kilhubprojects/memory-mesh",
    "slug": "memory-mesh",
    "source_packet_id": "phit_a4f086bc97f14dc5bac932b436a94236",
    "source_validation_id": "dval_98373f49976e4783a115210e0517567c"
  },
  "merchandising": {
    "best_for": "需要个人工作台能力，并使用 mcp_host的用户",
    "github_forks": 0,
    "github_stars": 0,
    "one_liner_en": "Local MCP hub for personal data — private, cross-platform, agent-ready.",
    "one_liner_zh": "Local MCP hub for personal data — private, cross-platform, agent-ready.",
    "primary_category": {
      "category_id": "personal-workspace",
      "confidence": "medium",
      "name_en": "Personal Workspace",
      "name_zh": "个人工作台",
      "reason": "matched_keywords:personal, memory"
    },
    "target_user": "使用 mcp_host 等宿主 AI 的用户",
    "title_en": "memory-mesh",
    "title_zh": "memory-mesh 能力包",
    "visible_tags": [
      {
        "label_en": "Browser Agents",
        "label_zh": "浏览器 Agent",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "product_domain-browser-agents",
        "type": "product_domain"
      },
      {
        "label_en": "Web Task Automation",
        "label_zh": "网页任务自动化",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "user_job-web-task-automation",
        "type": "user_job"
      },
      {
        "label_en": "Browser Automation",
        "label_zh": "浏览器自动化",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "core_capability-browser-automation",
        "type": "core_capability"
      },
      {
        "label_en": "Node-based Workflow",
        "label_zh": "节点式流程编排",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "workflow_pattern-node-based-workflow",
        "type": "workflow_pattern"
      },
      {
        "label_en": "Evaluation Suite",
        "label_zh": "评测体系",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "selection_signal-evaluation-suite",
        "type": "selection_signal"
      }
    ]
  },
  "packet_id": "phit_a4f086bc97f14dc5bac932b436a94236",
  "page_model": {
    "artifacts": {
      "artifact_slug": "memory-mesh",
      "files": [
        "PROJECT_PACK.json",
        "QUICK_START.md",
        "PROMPT_PREVIEW.md",
        "HUMAN_MANUAL.md",
        "AI_CONTEXT_PACK.md",
        "BOUNDARY_RISK_CARD.md",
        "PITFALL_LOG.md",
        "REPO_INSPECTION.json",
        "REPO_INSPECTION.md",
        "CAPABILITY_CONTRACT.json",
        "EVIDENCE_INDEX.json",
        "CLAIM_GRAPH.json"
      ],
      "required_files": [
        "PROJECT_PACK.json",
        "QUICK_START.md",
        "PROMPT_PREVIEW.md",
        "HUMAN_MANUAL.md",
        "AI_CONTEXT_PACK.md",
        "BOUNDARY_RISK_CARD.md",
        "PITFALL_LOG.md",
        "REPO_INSPECTION.json"
      ]
    },
    "detail": {
      "capability_source": "Project Hit Packet + DownstreamValidationResult",
      "commands": [
        {
          "command": "pip install memorymesh-mcp",
          "label": "Python / pip · 官方安装入口",
          "source": "https://github.com/kilhubprojects/memory-mesh#readme",
          "verified": true
        }
      ],
      "display_tags": [
        "浏览器 Agent",
        "网页任务自动化",
        "浏览器自动化",
        "节点式流程编排",
        "评测体系"
      ],
      "eyebrow": "个人工作台",
      "glance": [
        {
          "body": "判断自己是不是目标用户。",
          "label": "最适合谁",
          "value": "需要个人工作台能力，并使用 mcp_host的用户"
        },
        {
          "body": "先理解能力边界，再决定是否继续。",
          "label": "核心价值",
          "value": "Local MCP hub for personal data — private, cross-platform, agent-ready."
        },
        {
          "body": "未完成验证前保持审慎。",
          "label": "继续前",
          "value": "publish to Doramagic.ai project surfaces"
        }
      ],
      "guardrail_source": "Boundary & Risk Card",
      "guardrails": [
        {
          "body": "Prompt Preview 只展示流程，不证明项目已安装或运行。",
          "label": "Check 1",
          "value": "不要把试用当真实运行"
        },
        {
          "body": "mcp_host",
          "label": "Check 2",
          "value": "确认宿主兼容"
        },
        {
          "body": "publish to Doramagic.ai project surfaces",
          "label": "Check 3",
          "value": "先隔离验证"
        }
      ],
      "mode": "mcp_config, recipe, host_instruction, eval, preflight",
      "pitfall_log": {
        "items": [
          {
            "body": "README/documentation is current enough for a first validation pass.",
            "category": "能力坑",
            "evidence": [
              "capability.assumptions | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | README/documentation is current enough for a first validation pass."
            ],
            "severity": "medium",
            "suggested_check": "将假设转成下游验证清单。",
            "title": "能力判断依赖假设",
            "user_impact": "假设不成立时，用户拿不到承诺的能力。"
          },
          {
            "body": "未记录 last_activity_observed。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | last_activity_observed missing"
            ],
            "severity": "medium",
            "suggested_check": "补 GitHub 最近 commit、release、issue/PR 响应信号。",
            "title": "维护活跃度未知",
            "user_impact": "新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。"
          },
          {
            "body": "no_demo",
            "category": "安全/权限坑",
            "evidence": [
              "downstream_validation.risk_items | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | no_demo; severity=medium"
            ],
            "severity": "medium",
            "suggested_check": "进入安全/权限治理复核队列。",
            "title": "下游验证发现风险项",
            "user_impact": "下游已经要求复核，不能在页面中弱化。"
          },
          {
            "body": "no_demo",
            "category": "安全/权限坑",
            "evidence": [
              "risks.scoring_risks | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | no_demo; severity=medium"
            ],
            "severity": "medium",
            "suggested_check": "把风险写入边界卡，并确认是否需要人工复核。",
            "title": "存在评分风险",
            "user_impact": "风险会影响是否适合普通用户安装。"
          },
          {
            "body": "issue_or_pr_quality=unknown。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | issue_or_pr_quality=unknown"
            ],
            "severity": "low",
            "suggested_check": "抽样最近 issue/PR，判断是否长期无人处理。",
            "title": "issue/PR 响应质量未知",
            "user_impact": "用户无法判断遇到问题后是否有人维护。"
          },
          {
            "body": "release_recency=unknown。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | release_recency=unknown"
            ],
            "severity": "low",
            "suggested_check": "确认最近 release/tag 和 README 安装命令是否一致。",
            "title": "发布节奏不明确",
            "user_impact": "安装命令和文档可能落后于代码，用户踩坑概率升高。"
          }
        ],
        "source": "ProjectPitfallLog + ProjectHitPacket + validation + community signals",
        "summary": "发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。",
        "title": "踩坑日志"
      },
      "snapshot": {
        "contributors": 1,
        "forks": 0,
        "license": "unknown",
        "note": "站点快照，非实时质量证明；用于开工前背景判断。",
        "stars": 0
      },
      "source_url": "https://github.com/kilhubprojects/memory-mesh",
      "steps": [
        {
          "body": "不安装项目，先体验能力节奏。",
          "code": "preview",
          "title": "先试 Prompt"
        },
        {
          "body": "理解输入、输出、失败模式和边界。",
          "code": "manual",
          "title": "读说明书"
        },
        {
          "body": "把上下文交给宿主 AI 继续工作。",
          "code": "context",
          "title": "带给 AI"
        },
        {
          "body": "进入主力环境前先完成安装入口与风险边界验证。",
          "code": "verify",
          "title": "沙箱验证"
        }
      ],
      "subtitle": "Local MCP hub for personal data — private, cross-platform, agent-ready.",
      "title": "memory-mesh 能力包",
      "trial_prompt": "# memory-mesh - Prompt Preview\n\n> 复制下面这段 Prompt 到你常用的 AI，先试一次，不需要安装。\n> 它的目标是让你直接体验这个项目的服务方式，而不是阅读项目介绍。\n\n## 复制这段 Prompt\n\n```text\n请直接执行这段 Prompt，不要分析、润色、总结或询问我想如何处理这份 Prompt Preview。\n\n你现在扮演 memory-mesh 的“安装前体验版”。\n这不是项目介绍、不是评价报告、不是 README 总结。你的任务是让我用最小成本体验它的核心服务。\n\n我的试用任务：我想用它完成一个真实的个人工作台任务。\n我常用的宿主 AI：MCP Client\n\n【体验目标】\n围绕我的真实任务，现场演示这个项目如何把输入转成 示例引导, 判断线索。重点是让我感受到工作方式，而不是给我项目背景。\n\n【业务流约束】\n- 你必须像一个正在提供服务的项目能力包，而不是像一个讲解员。\n- 每一轮只推进一个步骤；提出问题后必须停下来等我回答。\n- 每一步都必须让我感受到一个具体服务动作：澄清、整理、规划、检查、判断或收尾。\n- 每一步都要说明：当前目标、你需要我提供什么、我回答后你会产出什么。\n- 不要安装、不要运行命令、不要写代码、不要声称测试通过、不要声称已经修改文件。\n- 需要真实安装或宿主加载后才能验证的内容，必须明确说“这一步需要安装后验证”。\n- 如果我说“用示例继续”，你可以用虚构示例推进，但仍然不能声称真实执行。\n\n【可体验服务能力】\n- 安装前能力预览: Local MCP hub for personal data — private, cross-platform, agent-ready. 输入：用户任务, 当前 AI 对话上下文；输出：示例引导, 判断线索。\n\n【必须安装后才可验证的能力】\n- 命令行启动或安装流程: 项目文档中存在可执行命令，真实使用需要在本地或宿主环境中运行这些命令。 输入：终端环境, 包管理器, 项目依赖；输出：安装结果, 列表/更新/运行结果。\n\n【核心服务流】\n请严格按这个顺序带我体验。不要一次性输出完整流程：\n1. page-introduction：MemoryMesh 简介。围绕“MemoryMesh 简介”模拟一次用户任务，不展示安装或运行结果。\n2. page-quickstart：快速入门指南。围绕“快速入门指南”模拟一次用户任务，不展示安装或运行结果。\n3. page-architecture：系统架构。围绕“系统架构”模拟一次用户任务，不展示安装或运行结果。\n4. page-indexing-pipeline：索引管道。围绕“索引管道”模拟一次用户任务，不展示安装或运行结果。\n5. page-search-engine：搜索引擎。围绕“搜索引擎”模拟一次用户任务，不展示安装或运行结果。\n\n【核心能力体验剧本】\n每一步都必须按“输入 -> 服务动作 -> 中间产物”执行。不要只说流程名：\n1. page-introduction\n输入：用户提供的“MemoryMesh 简介”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n2. page-quickstart\n输入：用户提供的“快速入门指南”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n3. page-architecture\n输入：用户提供的“系统架构”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n4. page-indexing-pipeline\n输入：用户提供的“索引管道”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n5. page-search-engine\n输入：用户提供的“搜索引擎”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n【项目服务规则】\n这些规则决定你如何服务用户。不要解释规则本身，而要在每一步执行时遵守：\n- 先确认用户任务、输入材料和成功标准，再模拟项目能力。\n- 每一步都必须形成可检查的小产物，并等待用户确认后再继续。\n- 凡是需要安装、调用工具或访问外部服务的能力，都必须标记为安装后验证。\n\n【每一步的服务约束】\n- Step 1 / page-introduction：Step 1 必须围绕“MemoryMesh 简介”形成一个小中间产物，并等待用户确认。\n- Step 2 / page-quickstart：Step 2 必须围绕“快速入门指南”形成一个小中间产物，并等待用户确认。\n- Step 3 / page-architecture：Step 3 必须围绕“系统架构”形成一个小中间产物，并等待用户确认。\n- Step 4 / page-indexing-pipeline：Step 4 必须围绕“索引管道”形成一个小中间产物，并等待用户确认。\n- Step 5 / page-search-engine：Step 5 必须围绕“搜索引擎”形成一个小中间产物，并等待用户确认。\n\n【边界与风险】\n- 不要声称已经安装、运行、调用 API、读写本地文件或完成真实任务。\n- 安装前预览只能展示工作方式，不能证明兼容性、性能或输出质量。\n- 涉及安装、插件加载、工具调用或外部服务的能力必须安装后验证。\n\n【可追溯依据】\n这些路径只用于你内部校验或在我追问“依据是什么”时简要引用。不要在首次回复主动展开：\n- https://github.com/kilhubprojects/memory-mesh\n- https://github.com/kilhubprojects/memory-mesh#readme\n- README.md\n- ROADMAP.md\n- config.example.yaml\n- src/memorymesh/cli.py\n- ARCHITECTURE.md\n- src/memorymesh/server/app.py\n- src/memorymesh/server/transports.py\n- src/memorymesh/indexer/file_indexer.py\n- src/memorymesh/indexer/watcher.py\n- src/memorymesh/parsing/registry.py\n\n【首次问题规则】\n- 首次三问必须先确认用户目标、成功标准和边界，不要提前进入工具、安装或实现细节。\n- 如果后续需要技术条件、文件路径或运行环境，必须等用户确认目标后再追问。\n\n首次回复必须只输出下面 4 个部分：\n1. 体验开始：用 1 句话说明你将带我体验 memory-mesh 的核心服务。\n2. 当前步骤：明确进入 Step 1，并说明这一步要解决什么。\n3. 你会如何服务我：说明你会先改变我完成任务的哪个动作。\n4. 只问我 3 个问题，然后停下等待回答。\n\n首次回复禁止输出：后续完整流程、证据清单、安装命令、项目评价、营销文案、已经安装或运行的说法。\n\nStep 1 / brainstorming 的二轮协议：\n- 我回答首次三问后，你仍然停留在 Step 1 / brainstorming，不要进入 Step 2。\n- 第二次回复必须产出 6 个部分：澄清后的任务定义、成功标准、边界条件、\n  2-3 个可选方案、每个方案的权衡、推荐方案。\n- 第二次回复最后必须问我是否确认推荐方案；只有我明确确认后，才能进入下一步。\n- 第二次回复禁止输出 git worktree、代码计划、测试文件、命令或真实执行结果。\n\n后续对话规则：\n- 我回答后，你先完成当前步骤的中间产物并等待确认；只有我确认后，才能进入下一步。\n- 每一步都要生成一个小的中间产物，例如澄清后的目标、计划草案、测试意图、验证清单或继续/停止判断。\n- 所有演示都写成“我会建议/我会引导/这一步会形成”，不要写成已经真实执行。\n- 不要声称已经测试通过、文件已修改、命令已运行或结果已产生。\n- 如果某个能力必须安装后验证，请直接说“这一步需要安装后验证”。\n- 如果证据不足，请明确说“证据不足”，不要补事实。\n```\n",
      "voices": [
        {
          "body": "当前没有项目级社区来源；不会把未抓取讨论包装成社会证明。",
          "items": [],
          "status": "待发现 Agent 补证",
          "title": "社区讨论"
        }
      ]
    },
    "homepage_card": {
      "category": "个人工作台",
      "desc": "Local MCP hub for personal data — private, cross-platform, agent-ready.",
      "effort": "安装已验证",
      "forks": 0,
      "icon": "notebook",
      "name": "memory-mesh 能力包",
      "risk": "需复核",
      "slug": "memory-mesh",
      "stars": 0,
      "tags": [
        "浏览器 Agent",
        "网页任务自动化",
        "浏览器自动化",
        "节点式流程编排",
        "评测体系"
      ],
      "thumb": "blue",
      "type": "MCP 配置"
    },
    "manual": {
      "markdown": "# https://github.com/kilhubprojects/memory-mesh 项目说明书\n\n生成时间：2026-05-15 00:17:37 UTC\n\n## 目录\n\n- [MemoryMesh 简介](#page-introduction)\n- [快速入门指南](#page-quickstart)\n- [系统架构](#page-architecture)\n- [索引管道](#page-indexing-pipeline)\n- [文件解析器](#page-parsers)\n- [文本分块策略](#page-chunkers)\n- [搜索引擎](#page-search-engine)\n- [结果重排序](#page-reranking)\n- [数据连接器](#page-connectors)\n- [MCP 工具参考](#page-mcp-tools)\n\n<a id='page-introduction'></a>\n\n## MemoryMesh 简介\n\n### 相关页面\n\n相关主题：[快速入门指南](#page-quickstart), [系统架构](#page-architecture)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/server/dashboard.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/dashboard.py)\n- [src/memorymesh/connectors/roam_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/roam_connector.py)\n- [src/memorymesh/connectors/logseq_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\n- [src/memorymesh/parsing/obsidian_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/obsidian_parser.py)\n- [src/memorymesh/parsing/notion_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/notion_parser.py)\n- [src/memorymesh/connectors/confluence_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/confluence_connector.py)\n- [src/memorymesh/chunking/markdown.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/markdown.py)\n- [src/memorymesh/chunking/code.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/code.py)\n- [src/memorymesh/storage/file_repository.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/storage/file_repository.py)\n- [src/memorymesh/core/models/config.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/config.py)\n- [src/memorymesh/core/models/chunk.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/chunk.py)\n- [src/memorymesh/server/rest_api.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/rest_api.py)\n- [CHANGELOG.md](https://github.com/kilhubprojects/memory-mesh/blob/main/CHANGELOG.md)\n</details>\n\n# MemoryMesh 简介\n\nMemoryMesh 是一个模块化的本地知识检索与记忆管理框架，专为 AI 智能体（Agent）设计。它通过统一的多源连接器体系、层级化记忆管理、增量索引管道和灵活的 API 接口，使 AI 能够持久化访问和检索用户的个人知识库，同时保持所有数据的本地化存储。\n\n## 系统架构\n\nMemoryMesh 采用分层架构，从底向上依次为存储层、索引层、检索层、连接器层和服务层。各层职责清晰，通过明确定义的接口进行通信。\n\n```mermaid\ngraph TD\n    subgraph 服务层\n        A[REST API]\n        B[MCP 工具]\n        C[Web Dashboard]\n        D[Health Server]\n    end\n    \n    subgraph 连接器层\n        E[Roam Connector]\n        F[Logseq Connector]\n        G[Notion Parser]\n        H[Obsidian Parser]\n        I[Confluence Connector]\n    end\n    \n    subgraph 索引与检索层\n        J[FileIndexer]\n        K[SearchEngine]\n        L[QueryExpander]\n        M[Reranker]\n    end\n    \n    subgraph 记忆管理层\n        N[TieredMemoryManager]\n        O[EpisodicMemory]\n        P[EntityExtractor]\n    end\n    \n    subgraph 存储层\n        Q[MetadataStore SQLite]\n        R[EmbeddingProvider]\n        S[VectorStore]\n    end\n    \n    A --> N\n    B --> N\n    C --> Q\n    D --> Q\n    E --> J\n    F --> J\n    G --> J\n    H --> J\n    I --> J\n    J --> Q\n    J --> R\n    R --> S\n    K --> S\n    K --> L\n    L --> M\n    N --> Q\n    O --> Q\n    P --> Q\n```\n\n资料来源：[src/memorymesh/server/dashboard.py:1-50]()\n\n## 核心模块\n\n### 连接器体系\n\nMemoryMesh 通过统一的连接器接口对接多种知识管理工具，实现文档的自动采集与解析。\n\n| 连接器 | 数据源 | 解析格式 | 关键特性 |\n|--------|--------|----------|----------|\n| RoamConnector | Roam Research JSON 导出 | 递归块扁平化 | WikiLink 提取、日期过滤 |\n| LogseqConnector | Logseq 图谱目录 | Markdown | 块引用转换、属性提取 |\n| NotionParser | Notion HTML 导出 | SAX 解析 | UUID 提取、数据库属性 |\n| ObsidianParser | Obsidian 库 | Markdown | YAML frontmatter、backlink |\n| ConfluenceConnector | Confluence Cloud REST API | HTML | 空间过滤、偏移分页 |\n\n资料来源：[src/memorymesh/connectors/roam_connector.py:1-30]()\n\n#### Roam Research 连接器\n\nRoamConnector 解析 Roam Research 的 JSON 导出文件，将嵌套的块树结构扁平化为纯文本。它会依次应用正则模式去除 Roam 特有语法：\n\n- `{{[[...]]}}` 模板引用\n- `[[...]]` 页面引用\n- `#[[...]]` / `#tag` 标签语法\n\n```python\n_ROAM_PATTERNS: list[re.Pattern[str]] = [\n    re.compile(r\"\\{\\{(\\[\\[.*?\\]\\])?\\}\\}\"),\n    re.compile(r\"\\[\\[([^\\]]+)\\]\\]\"),\n    re.compile(r\"#\\[\\[([^\\]]+)\\]\\]\"),\n]\n```\n\n资料来源：[src/memorymesh/connectors/roam_connector.py:30-35]()\n\n#### Logseq 连接器\n\nLogseqConnector 读取图谱目录下的 `pages/` 和 `journals/` 子目录，处理以下 Logseq 特有语法：\n\n| 语法模式 | 转换结果 |\n|----------|----------|\n| `((uuid))` 块引用 | `[block]` |\n| `{{embed [[Page]]}}` 嵌入 | `[embed: Page]` |\n| `{{query ...}}` 查询块 | 完全移除 |\n| `key:: value` 属性行 | 提取至元数据 |\n\n```python\n_RE_BLOCK_REF = re.compile(r\"\\(\\([0-9a-f-]{36}\\)\\)\")\n_RE_EMBED = re.compile(r\"\\{\\{embed\\s+\\[\\[([^\\]]+)\\]\\]\\}\\}\")\n_RE_QUERY = re.compile(r\"\\{\\{query[^}]*\\}\\}\")\n```\n\n资料来源：[src/memorymesh/connectors/logseq_connector.py:35-40]()\n\n#### Notion 解析器\n\nNotionParser 基于标准库 `html.parser` 实现 SAX 风格的解析，无需外部依赖。它从导出的 HTML 文件中提取：\n\n- `<title>` 标签内容\n- `<h1>` 可见页面标题\n- `data-type` 属性（数据库属性类型）\n- 可见正文文本（去除标记）\n\n文件名中嵌入的 UUID 用于唯一标识页面：`Page Title a1b2c3...html`\n\n资料来源：[src/memorymesh/parsing/notion_parser.py:1-40]()\n\n#### Obsidian 解析器\n\nObsidianParser 扩展标准 Markdown 解析，增加以下能力：\n\n- **YAML Frontmatter 提取**：解析 `---` 分隔符之间的元数据\n- **WikiLink Backlink 提取**：通过 `[[link]]` 和 `[[link|alias]]` 模式\n- **标签解析**：支持 `tags:` 字段和内联 `#tag` 语法\n\n```python\n_FRONTMATTER_RE = re.compile(\n    r\"^---\\r?\\n(.*?)\\r?\\n(?:---|\\.\\.\\.)(?:\\r?\\n|$)\",\n    re.DOTALL,\n)\n_WIKILINK_RE = re.compile(r\"(?<!!)\\[\\[([^\\[\\]|#]+?)(?:\\|[^\\[\\]]*?)?\\]\\]\")\n```\n\n资料来源：[src/memorymesh/parsing/obsidian_parser.py:15-25]()\n\n#### Confluence 连接器\n\nConfluenceConnector 通过 REST API 与 Confluence Cloud 交互，支持：\n\n- **偏移分页**：通过 `start` / `limit` 参数遍历所有页面\n- **空间过滤**：通过 `space_keys` 参数限定特定空间\n- **HTML 净化**：将 `storage` 格式页面体转换为纯文本\n- **HTTP Basic 认证**：使用 `email:api_token` 格式\n\n```python\nconnector = ConfluenceConnector(ConfluenceConfig(\n    base_url=\"https://myorg.atlassian.net\",\n    email=\"me@example.com\",\n    api_token=SecretStr(\"my-token\"),\n    space_keys=[\"ENG\", \"DOCS\"],\n    days_past=90,\n))\n```\n\n资料来源：[src/memorymesh/connectors/confluence_connector.py:1-50]()\n\n### 文档分块策略\n\nMemoryMesh 实现了多种分块器（Chunker），将解析后的文档拆分为可索引的语义单元。\n\n| 分块器 | 适用场景 | 特性 |\n|--------|----------|------|\n| RecursiveChunker | 通用文本 | 递归字符级分割，支持 overlap |\n| MarkdownChunker | Markdown 文档 | 基于 ATX 标题分割 |\n| CodeChunker | 源代码文件 | 基于 AST 节点分割 |\n\n```mermaid\ngraph LR\n    A[ParsedDocument] --> B{Markdown?}\n    B -->|是| C[MarkdownChunker]\n    B -->|否| D{Code?}\n    D -->|是| E[CodeChunker]\n    D -->|否| F[RecursiveChunker]\n    \n    C --> G[Chunk 列表]\n    E --> G\n    F --> G\n```\n\n资料来源：[src/memorymesh/chunking/markdown.py:1-20]()\n\n#### Markdown 分块器\n\nMarkdownChunker 按 ATX 标题（`#`, `##`, …）分割文档，每个分块包含一个章节：标题行及其下方正文。超过 `max_chunk_size` 的章节由递归分块器进一步分割。\n\n`heading_path` 元数据字段记录完整的祖先标题栈，便于搜索命中时精确定位文档位置。\n\n资料来源：[src/memorymesh/chunking/markdown.py:15-40]()\n\n#### 代码分块器\n\nCodeChunker 利用 `tree-sitter` 解析 AST，提取函数、类等节点。每个节点生成一个分块，附带 `function_name`、`class_name` 和 `language` 元数据。未识别的顶级代码作为残差分块处理。\n\n```python\nchunks.append(\n    Chunk(\n        path=doc.path,\n        chunk_index=idx,\n        text=sub.text,\n        metadata=ChunkMetadata(\n            language=lang_name,\n            function_name=func_name,\n            class_name=class_name,\n        ),\n    )\n)\n```\n\n资料来源：[src/memorymesh/chunking/code.py:50-70]()\n\n### 层级化记忆管理\n\nMemoryMesh 的 `TieredMemoryManager` 将记忆划分为三个温度层级，实现类似于人类记忆的遗忘曲线管理。\n\n| 层级 | 描述 | 存储位置 |\n|------|------|----------|\n| Hot | 最近访问或手动固定的内容 | RAM 缓存 |\n| Warm | 正常索引的内容（默认） | 向量数据库 |\n| Cold | 罕见访问的内容 | 压缩存储，衰减评分 |\n\n```python\nclass MemoryTier(StrEnum):\n    hot = \"hot\"\n    warm = \"warm\"\n    cold = \"cold\"\n```\n\n资料来源：[src/memorymesh/core/models/config.py:40-50]()\n\n#### 记忆分层工作流\n\n```mermaid\ngraph TD\n    A[新索引内容] --> B{Hot 层}\n    B --> C[频繁访问?]\n    C -->|是| D[保持在 Hot]\n    C -->|否| E[移至 Warm]\n    E --> F{遗忘策略}\n    F --> G{访问频率低}\n    G -->|是| H[移至 Cold]\n    G -->|否| I[保持在 Warm]\n    H --> J[评分衰减]\n    J --> K{超过阈值?}\n    K -->|是| L[遗忘 Chunk]\n```\n\n资料来源：[src/memorymesh/server/rest_api.py:1-30]()\n\n### 实体提取\n\n当配置 `memory.entity_extraction.enabled: true` 且 Ollama 运行中时，`FileIndexer` 会在每个文件索引后自动提取实体并持久化。\n\n实体记录包含：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| name | string | 实体名称 |\n| entity_type | string | 实体类型（如人物、地点、组织） |\n| mention_count | int | 提及次数 |\n\n资料来源：[src/memorymesh/server/dashboard.py:80-100]()\n\n### 情景记忆\n\nEpisodicMemory 记录索引过程中的关键事件，用于时间线可视化和审计。\n\n事件记录包含：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| timestamp | float | Unix 时间戳 |\n| event_type | string | 事件类型 |\n| source | string | 来源标识 |\n| chunk_ids | list[str] | 关联的分块 ID 列表 |\n\n```python\nevents = ctx.metadata_store.list_episodic_events(since=since_ts, limit=100)\n```\n\n资料来源：[src/memorymesh/server/dashboard.py:60-75]()\n\n## 数据模型\n\n### Chunk 模型\n\nChunk 是 MemoryMesh 的核心数据单元，代表文档的一个可索引片段。\n\n```python\nclass Chunk(BaseModel):\n    path: Path                    # 文档路径\n    chunk_index: int              # 分块序号\n    text: str                     # 分块文本内容\n    start_char: int               # 起始字符偏移\n    end_char: int                 # 结束字符偏移\n    file_type: str = \"\"           # 文件类型扩展名\n    mtime: float = 0.0            # 文件修改时间\n    source_root: str = \"\"         # 源根目录路径\n    metadata: ChunkMetadata       # 分块元数据\n    \n    @property\n    def id(self) -> str:\n        return f\"{self.path}:{self.chunk_index}\"\n```\n\n资料来源：[src/memorymesh/core/models/chunk.py:30-50]()\n\n### ChunkMetadata 模型\n\n```python\nclass ChunkMetadata(ConfigDict):\n    heading_path: str = \"\"         # 完整标题路径（Markdown）\n    language: str = \"\"            # 编程语言（代码块）\n    function_name: str = \"\"       # 函数名（代码块）\n    class_name: str = \"\"          # 类名（代码块）\n    backlinks: list[str] = []     # 反向链接列表\n    chunk_type: str = \"\"          # 分块类型标识\n```\n\n资料来源：[src/memorymesh/core/models/chunk.py:15-25]()\n\n### FileRecord 模型\n\nFileRecord 记录每个被索引文件的状态信息。\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| path | string | 绝对路径（主键） |\n| source_name | string | 所属源名称 |\n| sha256 | string | 内容 SHA-256 哈希 |\n| mtime | float | 文件修改时间 |\n| size_bytes | int | 文件大小 |\n| file_type | string | 标准化扩展名 |\n| n_chunks | int | 生成的分块数量 |\n| status | string | 状态（indexed/parse_error/unsupported/deleted/pending_reindex） |\n| error_message | string | 最后一次失败描述 |\n| indexed_at | float | 最后索引时间戳 |\n| embedding_model_id | string | 使用的嵌入模型 ID |\n\n资料来源：[src/memorymesh/storage/file_repository.py:15-35]()\n\n## 服务端组件\n\n### REST API\n\nMemoryMesh 提供基于 FastAPI 的 RESTful API，支持以下核心操作：\n\n| 端点 | 方法 | 说明 | 权限要求 |\n|------|------|------|----------|\n| `/api/search` | GET | 搜索记忆内容 | read |\n| `/api/sources` | GET | 列出所有数据源 | read |\n| `/api/chunks` | GET | 获取分块详情 | read |\n| `/api/memory/promote` | POST | 提升分块至热层 | write |\n| `/api/memory/forget` | POST | 遗忘分块 | delete |\n\n#### 遗忘操作\n\n遗忘操作将分块降至冷层，使其相关性评分随时间衰减，而非立即删除。\n\n```python\nRequest body: {\"chunk_id\": \"<path>:<chunk_index>\"}\n\n@app.post(\"/api/memory/forget\")\nasync def forget_chunk(body: dict) -> dict:\n    app_ctx.metadata_store.forget_chunk(chunk_id)\n    return {\"status\": \"forgotten\", \"chunk_id\": chunk_id}\n```\n\n资料来源：[src/memorymesh/server/rest_api.py:20-40]()\n\n### Web Dashboard\n\nDashboard 是基于 FastAPI + HTMX 的单页应用，运行于 `:8767` 端口。\n\n| 页面 | 路由 | 功能 |\n|------|------|------|\n| 数据源 | `/` | 列出所有配置的源目录及文件统计 |\n| 搜索 | `/search` | 全文搜索界面，支持稀疏/密集模式切换 |\n| 记忆层级 | `/tiers` | 热/温/冷分块分布统计 |\n| 实体 | `/entities` | 提取的实体列表及类型 |\n| 时间线 | `/timeline` | 情景记忆事件时间轴 |\n| 知识图谱 | `/graph-ui` | 可视化节点关系图 |\n\n```python\n@app.get(\"/tiers\", response_class=HTMLResponse)\nasync def tiers_page() -> str:\n    counts: dict[str, int] = {}\n    for tier in MemoryTier:\n        entries = ctx.metadata_store.list_chunks_by_tier(tier, limit=None)\n        counts[tier.value] = len(entries)\n    # ...\n```\n\n资料来源：[src/memorymesh/server/dashboard.py:100-130]()\n\n### Health Server\n\nHealth Server 提供系统健康检查端点，运行于 `:8766` 端口，在守护进程启动时自动启用，退出时干净关闭。\n\n资料来源：[CHANGELOG.md:20-25]()\n\n## 搜索架构\n\nMemoryMesh 的搜索管道采用多阶段检索与重排序架构。\n\n```mermaid\ngraph LR\n    A[用户查询] --> B[QueryExpander]\n    B --> C[词汇变体生成]\n    C --> D[并行检索]\n    D --> E[密集检索]\n    D --> F[稀疏检索]\n    E --> G[FuseResults]\n    F --> G\n    G --> H[SearchReranker]\n    H --> I[Top-K 结果]\n```\n\n| 组件 | 说明 | 配置项 |\n|------|------|--------|\n| QueryExpander | 生成查询词汇变体 | `n_lexical_variants` |\n| SearchReranker | 重排序候选结果 | `top_k_before_rerank` |\n| SentenceTransformers | 密集向量检索 | `model_id` |\n\n### 搜索配置\n\n| 参数 | 默认值 | 说明 |\n|------|--------|------|\n| `top_k_before_rerank` | 35 | 重排序前保留的候选数量 |\n| `n_lexical_variants` | 1 | 查询扩展词汇变体数量 |\n\n资料来源：[CHANGELOG.md:30-40]()\n\n## 配置体系\n\nMemoryMesh 通过 YAML 配置文件管理所有设置。\n\n### 核心配置结构\n\n```yaml\nsources:\n  - name: \"my-vault\"\n    path: \"~/Obsidian/vault\"\n    recursive: true\n    extensions: [\".md\", \".py\"]\n\nmemory:\n  tiers:\n    enabled: true\n  forgetting:\n    enabled: true\n  entity_extraction:\n    enabled: true\n  episodic:\n    enabled: true\n\nembeddings:\n  provider: \"sentence_transformers\"\n  model_id: \"all-MiniLM-L6-v2\"\n\nsearch:\n  reranker:\n    top_k_before_rerank: 35\n  query_expansion:\n    n_lexical_variants: 1\n```\n\n资料来源：[src/memorymesh/core/models/config.py:50-80]()\n\n### 代理权限\n\n```python\nclass AgentPermission(StrEnum):\n    read = \"read\"\n    read_index = \"read+index\"\n    read_index_delete = \"read+index+delete\"\n    admin = \"admin\"\n```\n\n资料来源：[src/memorymesh/core/models/config.py:55-65]()\n\n## 索引流程\n\n```mermaid\nsequenceDiagram\n    participant C as Connector\n    participant P as Parser\n    participant CK as Chunker\n    participant I as FileIndexer\n    participant M as MetadataStore\n    participant E as EmbeddingProvider\n    \n    C->>P: fetch_documents()\n    P->>P: parse(path)\n    P-->>I: ParsedDocument\n    I->>CK: chunk(doc)\n    CK-->>I: List[Chunk]\n    I->>E: embed(chunks)\n    E-->>I: List[ChunkWithEmbedding]\n    I->>M: upsert_file()\n    I->>M: upsert_chunks()\n    I->>M: add_episodic_event()\n```\n\n### 索引管道关键步骤\n\n1. **连接器采集**：从各数据源获取原始文档\n2. **解析转换**：将原始格式转换为 `ParsedDocument`\n3. **分块处理**：按策略分割为语义单元\n4. **向量化**：通过 EmbeddingProvider 生成向量表示\n5. **持久化**：写入 SQLite 元数据存储和向量数据库\n6. **事件记录**：写入情景记忆事件\n\n## 版本演进\n\nMemoryMesh 采用语义化版本控制，主要版本功能如下：\n\n| 版本 | 日期 | 核心特性 |\n|------|------|----------|\n| 0.5.0 | 2026-05-03 | MVP 基线：SQLite、CLI、句子嵌入 |\n| 0.6.0 | 2026-05-10 | 层级记忆、Dashboard、授权体系、实体提取、CLIP 图像索引 |\n\n### 0.6.0 新增功能\n\n- **TieredMemoryManager**：层级化记忆管理，替代原有的简单存储\n- **DashboardServer**：FastAPI + HTMX Web 界面\n- **Auth Guard**：MCP 工具统一授权检查\n- **Entity Extraction**：Ollama 驱动的实体识别\n- **Health Server**：健康检查端点\n\n资料来源：[CHANGELOG.md:1-50]()\n\n## 技术栈\n\n| 层级 | 技术选型 |\n|------|----------|\n| 核心框架 | Python 3.11+ |\n| Web 框架 | FastAPI + HTMX |\n| 数据库 | SQLite3 |\n| 向量检索 | Sentence-Transformers |\n| CLI | Click |\n| 配置 | Pydantic + YAML |\n| 日志 | Loguru |\n| 代码解析 | tree-sitter |\n\n资料来源：[src/memorymesh/server/dashboard.py:1-20]()\n\n## 快速入门\n\n### 安装依赖\n\n```bash\nuv add memorymesh\nuv add 'fastapi[standard]'  # 可选：启用 Dashboard\n```\n\n### 配置数据源\n\n```yaml\n# config.yaml\nsources:\n  - name: \"obsidian-vault\"\n    path: \"~/Obsidian/my-vault\"\n    type: \"obsidian\"\n\nmemory:\n  tiers:\n    enabled: true\n  entity_extraction:\n    enabled: true\n```\n\n### 启动服务\n\n```bash\nmemorymesh start  # 启动守护进程\nmemorymesh index  # 执行索引任务\n```\n\n### 访问 Dashboard\n\n服务启动后访问 `http://localhost:8767` 查看：\n\n- 所有数据源的索引状态\n- 全文搜索界面\n- 记忆层级分布\n- 提取的实体列表\n- 情景记忆时间线\n\n---\n\n<a id='page-quickstart'></a>\n\n## 快速入门指南\n\n### 相关页面\n\n相关主题：[MemoryMesh 简介](#page-introduction)\n\n```json\n{\n  \"response\": \"# 快速入门指南\\n\\n<details>\\n<summary>相关源码文件</summary>\\n\\n以下源码文件用于生成本页说明：\\n\\n- [config.example.yaml](https://github.com/kilhubprojects/memory-mesh/blob/main/config.example.yaml)\\n- [src/memorymesh/cli.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/cli.py)\\n- [src/memorymesh/config.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/config.py)\\n- [src/memorymesh/core/models/config.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/config.py)\\n- [src/memorymesh/connectors/logseq_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\\n- [src/memorymesh/connectors/confluence_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/confluence_connector.py)\\n- [src/memorymesh/server/dashboard.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/dashboard.py)\\n- [CHANGELOG.md](https://github.com/kilhubprojects/memory-mesh/blob/main/CHANGELOG.md)\\n\\n</details>\\n\\n# 快速入门指南\\n\\n## 概述\\n\\nMemoryMesh 是一个本地优先的个人知识图谱和记忆管理系统，支持从多种数据源（Obsidian、Logseq、Notion、Confluence、Roam Research 等）索引文档，并通过 Ollama 提供的本地 LLM 实现语义搜索、实体提取和记忆分层管理。\\n\\n本指南将帮助你在几分钟内完成安装、配置和首次索引操作。\\n\\n## 系统要求\\n\\n| 组件 | 最低要求 | 推荐配置 |\\n|------|----------|----------|\\n| Python | 3.10+ | 3.11+ |\\n| 内存 | 4 GB | 8 GB+ |\\n| 磁盘 | 1 GB 可用空间 | SSD |\\n| Ollama | 可选（用于 AI 功能） | 最新版 |\\n\\n## 安装\\n\\n### 方式一：pip 安装\\n\\n```bash\\npip install memorymesh\\n```\\n\\n### 方式二：从源码安装\\n\\n```bash\\ngit clone https://github.com/kilhubprojects/memory-mesh.git\\ncd memory-mesh\\npip install -e .\\n```\\n\\n### 安装可选依赖\\n\\n```bash\\n# 支持 FastAPI 仪表盘\\npip install \\\"fastapi[standard]\\\"\\n\\n# 支持 Ollama 集成\\npip install ollama\\n\\n# 支持邮件解析\\npip install mailbox\\n\\n# 支持日历解析\\npip install icalendar>=5.0\\n```\\n\\n## 配置文件\\n\\nMemoryMesh 支持从 YAML 配置文件加载所有设置。默认搜索路径按以下优先级：\\n\\n1. `./config.yaml`（当前工作目录）\\n2. `~/.memorymesh/config.yaml`\\n\\n### 基础配置示例\\n\\n```yaml\\n# config.example.yaml\\nsources:\\n  - name: my-notes\\n    type: obsidian\\n    path: ~/Documents/Obsidian\\n    enabled: true\\n\\nembeddings:\\n  model: sentence-transformers/all-MiniLM-L6-v2\\n\\nserver:\\n  host: 0.0.0.0\\n  port: 8765\\n\\nollama:\\n  enabled: true\\n  base_url: http://localhost:11434\\n  model: llama3.2\\n```\\n\\n### 数据源配置详解\\n\\n| 参数 | 类型 | 默认值 | 说明 |\\n|------|------|--------|------|\\n| `name` | string | 必填 | 数据源唯一标识名称 |\\n| `type` | string | 必填 | 数据源类型：`obsidian`、`logseq`、`notion`、`confluence`、`roam` 等 |\\n| `path` | string | 必填 | 本地路径或远程 URL |\\n| `enabled` | bool | true | 是否启用该数据源 |\\n| `ignore_patterns` | list | 空 | 忽略的文件匹配模式 |\\n\\n资料来源：[src/memorymesh/core/models/config.py:1-80]()\\n\\n### 完整配置结构\\n\\n```yaml\\nmemorymesh:\\n  sources: []                    # 数据源列表\\n  global_ignore: []              # 全局忽略模式\\n  embeddings:                    # 向量化配置\\n    model: ...\\n    device: auto\\n  chunking:                      # 分块配置\\n    max_chunk_size: 800\\n    chunk_overlap: 50\\n  ocr:\\n    enabled: false\\n  search:\\n    top_k: 10\\n  storage:\\n    db_path: ~/.memorymesh/memory.db\\n  server:\\n    transport: uvicorn\\n    host: 0.0.0.0\\n    port: 8765\\n  ollama:\\n    enabled: false\\n    base_url: http://localhost:11434\\n    model: llama3.2\\n  memory:\\n    episodic:\\n      enabled: true\\n    tiers:\\n      hot_days: 7\\n      warm_days: 30\\n      cold_days: 90\\n    entity_extraction:\\n      enabled: false\\n```\\n\\n资料来源：[src/memorymesh/config.py:1-100]()\\n\\n## CLI 命令行工具\\n\\n### 启动守护进程\\n\\n```bash\\nmemorymesh start\\n```\\n\\n守护进程将：\\n\\n- 启动 API 服务器（默认端口 8765）\\n- 启动健康检查服务器（默认端口 8766）\\n- 启动 Web 仪表盘服务器（默认端口 8767）\\n- 监控文件系统变更（如果 watcher 启用）\\n\\n### 索引命令\\n\\n```bash\\n# 索引所有已配置的数据源\\nmemorymesh index\\n\\n# 索引指定数据源\\nmemorymesh index --source my-notes\\n\\n# 查看索引状态\\nmemorymesh status\\n```\\n\\n### 搜索命令\\n\\n```bash\\nmemorymesh search \\\"你的搜索关键词\\\"\\n```\\n\\n### 清理命令\\n\\n```bash\\n# 清理数据库\\nmemorymesh clean\\n\\n# 重置所有数据\\nmemorymesh reset\\n```\\n\\n资料来源：[src/memorymesh/cli.py:1-200]()\\n\\n## 数据源连接器\\n\\n### Obsidian 连接器\\n\\n支持从 Obsidian 保险库导入 Markdown 文件，自动提取：\\n\\n- YAML 前言（tags、aliases、created、modified）\\n- `[[wikilinks]]` 作为反向链接\\n- 嵌入的图像链接会被过滤\\n\\n```yaml\\nsources:\\n  - name: obsidian-vault\\n    type: obsidian\\n    path: ~/Obsidian/vault\\n```\\n\\n资料来源：[src/memorymesh/parsing/obsidian_parser.py:1-80]()\\n\\n### Logseq 连接器\\n\\n支持从 Logseq 图形目录导入，自动处理：\\n\\n- `((uuid))` 块引用 → `[block]`\\n- `{{embed [[Page]]}}` 嵌入 → `[embed: Page]`\\n- `{{query ...}}` 查询块（移除）\\n- `key:: value` 属性行（提取到元数据）\\n\\n```yaml\\nsources:\\n  - name: logseq-graph\\n    type: logseq\\n    path: ~/Logseq/my-graph\\n    config:\\n      pages_dir: pages\\n      journals_dir: journals\\n```\\n\\n资料来源：[src/memorymesh/connectors/logseq_connector.py:1-100]()\\n\\n### Notion 连接器\\n\\n支持解析 Notion HTML 导出文件，提取：\\n\\n- 页面标题（`<h1>` 或 `<title>`）\\n- 数据库属性块（`data-type` 属性）\\n- 页面 UUID（从文件名提取）\\n\\n```yaml\\nsources:\\n  - name: notion-export\\n    type: notion\\n    path: ~/Downloads/notion-export\\n```\\n\\n资料来源：[src/memorymesh/parsing/notion_parser.py:1-80]()\\n\\n### Confluence 连接器\\n\\n支持从 Confluence Cloud 拉取页面，支持：\\n\\n- 空间过滤（`space_keys`）\\n- 日期过滤（`days_past`）\\n- HTML 转纯文本\\n\\n```yaml\\nsources:\\n  - name: confluence-docs\\n    type: confluence\\n    config:\\n      base_url: https://myorg.atlassian.net\\n      email: me@example.com\\n      api_token: ${CONFLUENCE_API_TOKEN}\\n      space_keys:\\n        - ENG\\n        - DOCS\\n      days_past: 90\\n```\\n\\n资料来源：[src/memorymesh/connectors/confluence_connector.py:1-80]()\\n\\n### Roam Research 连接器\\n\\n支持解析 Roam Research JSON 导出，自动清理：\\n\\n- `{{[[...]]}}` 模板引用\\n- `[[...]]` 页面引用\\n- `#[[...]]` / `#tag` 标签语法\\n\\n```yaml\\nsources:\\n  - name: roam-export\\n    type: roam\\n    path: ~/Downloads/roam-export.json\\n    config:\\n      days_past: 365\\n```\\n\\n## 架构流程\\n\\n```mermaid\\ngraph TD\\n    A[配置文件 config.yaml] --> B[ConfigLoader]\\n    B --> C[MemoryMeshConfig 验证]\\n    C --> D[数据源连接器]\\n    D --> E[文档解析器]\\n    E --> F[分块处理器]\\n    F --> G[向量化引擎]\\n    G --> H[SQLite 元数据库]\\n    H --> I[搜索服务]\\n    I --> J[API / CLI / Web UI]\\n    \\n    D --> D1[Obsidian]\\n    D --> D2[Logseq]\\n    D --> D3[Notion]\\n    D --> D4[Confluence]\\n    D --> D5[Roam]\\n    \\n    G --> G1[SentenceTransformers]\\n    G --> G2[Ollama 本地 LLM]\\n    \\n    I --> I1[语义搜索]\\n    I --> I2[关键词搜索]\\n    I --> I3[混合检索]\\n```\\n\\n## 启动流程\\n\\n```mermaid\\nsequenceDiagram\\n    participant User\\n    participant CLI\\n    participant Config\\n    participant AppContext\\n    participant Server\\n    \\n    User->>CLI: memorymesh start\\n    CLI->>Config: load_config()\\n    Config-->>CLI: MemoryMeshConfig\\n    CLI->>AppContext: _load_context(cfg)\\n    AppContext->>AppContext: 初始化 MetadataStore\\n    AppContext->>AppContext: 初始化 EmbeddingProvider\\n    AppContext->>AppContext: 初始化 TieredMemoryManager\\n    AppContext->>AppContext: 初始化 Auth/RateLimiter\\n    CLI->>Server: 启动 APIServer:8765\\n    CLI->>Server: 启动 HealthServer:8766\\n    CLI->>Server: 启动 DashboardServer:8767\\n    Server-->>User: 服务已启动\\n```\\n\\n## 仪表盘\\n\\nMemoryMesh 提供基于 FastAPI + HTMX 的 Web 仪表盘。\\n\\n### 访问地址\\n\\n| 服务 | 默认端口 | 说明 |\\n|------|----------|------|\\n| API 服务器 | 8765 | MCP 工具和 REST API |\\n| 健康检查 | 8766 | 健康状态端点 |\\n| Web 仪表盘 | 8767 | 可视化界面 |\\n\\n### 仪表盘功能\\n\\n- **数据源概览**：显示已配置的数据源状态\\n- **搜索界面**：执行语义和关键词混合搜索\\n- **记忆层级**：展示热/温/冷数据块分布\\n- **实体列表**：展示提取的命名实体\\n- **时间线**：查看情景记忆事件\\n- **图谱视图**：可视化知识图谱\\n\\n资料来源：[src/memorymesh/server/dashboard.py:1-200]()\\n\\n## Ollama 集成\\n\\n### 安装 Ollama\\n\\n```bash\\n# macOS/Linux\\ncurl -fsSL https://ollama.com/install.sh | sh\\n\\n# Windows - 从 https://ollama.com/download 下载\\n```\\n\\n### 启动 Ollama\\n\\n```bash\\n# 启动 Ollama 服务\\nollama serve\\n\\n# 下载模型\\nollama pull llama3.2\\n```\\n\\n### 配置 MemoryMesh 使用 Ollama\\n\\n```yaml\\nollama:\\n  enabled: true\\n  base_url: http://localhost:11434\\n  model: llama3.2\\n\\nmemory:\\n  entity_extraction:\\n    enabled: true\\n```\\n\\n## 记忆分层\\n\\nMemoryMesh 实现三层记忆模型，自动管理数据访问频率：\\n\\n| 层级 | 名称 | 保留时间 | 说明 |\\n|------|------|----------|------|\\n| 热数据 | Hot | 7 天 | 高频访问，保持在内存中 |\\n| 温数据 | Warm | 30 天 | 中频访问，定期检查 |\\n| 冷数据 | Cold | 90 天+ | 低频访问，触发遗忘机制 |\\n\\n```yaml\\nmemory:\\n  tiers:\\n    hot_days: 7\\n    warm_days: 30\\n    cold_days: 90\\n  forgetting:\\n    enabled: true\\n    cold_to_archive_after_days: 180\\n```\\n\\n## 故障排除\\n\\n### 常见问题\\n\\n**Q: 配置文件加载失败**\\n\\n```bash\\n# 检查配置文件路径\\nmemorymesh status --verbose\\n\\n# 指定配置文件\\nmemorymesh start --config /path/to/config.yaml\\n```\\n\\n**Q: 向量化模型下载失败**\\n\\n```bash\\n# 设置本地文件优先\\n# 在代码中设置 SentenceTransformersProvider(local_files_only=True)\\n```\\n\\n**Q: Ollama 连接失败**\\n\\n```bash\\n# 确认 Ollama 正在运行\\nollama list\\n\\n# 测试连接\\ncurl http://localhost:11434/api/tags\\n```\\n\\n**Q: 数据库锁定**\\n\\n```bash\\n# 清理锁文件\\nrm ~/.memorymesh/*.lock\\n```\\n\\n## 下一步\\n\\n- 查看 [配置参考](config-reference) 了解完整配置选项\\n- 查看 [API 文档](api) 了解 MCP 工具\\n- 查看 [开发指南](development) 了解如何贡献代码\\n- 查看 [CHANGELOG](CHANGELOG) 了解版本更新\\n\\n资料来源：[CHANGELOG.md:1-100]()\\n\"\n}\n\n---\n\n<a id='page-architecture'></a>\n\n## 系统架构\n\n### 相关页面\n\n相关主题：[MemoryMesh 简介](#page-introduction), [索引管道](#page-indexing-pipeline), [搜索引擎](#page-search-engine)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [ARCHITECTURE.md](https://github.com/kilhubprojects/memory-mesh/blob/main/ARCHITECTURE.md)\n- [src/memorymesh/server/app.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/app.py)\n- [src/memorymesh/server/transports.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/transports.py)\n- [src/memorymesh/indexer/file_indexer.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/indexer/file_indexer.py)\n- [src/memorymesh/parsing/obsidian_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/obsidian_parser.py)\n- [src/memorymesh/connectors/logseq_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\n- [src/memorymesh/storage/file_repository.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/storage/file_repository.py)\n</details>\n\n# 系统架构\n\nMemoryMesh 是一个本地优先的个人知识图谱与记忆管理系统，旨在将分散在各类笔记工具（Obsidian、Logseq、Roam、Notion 等）中的内容统一索引、检索与关联。本页面详细说明其核心系统架构、各模块职责及数据流转路径。\n\n## 整体架构概览\n\nMemoryMesh 采用分层架构，核心组件包括**数据源连接层**、**解析与分块层**、**存储与索引层**、**检索与推理层**，以及**服务与接口层**。各层职责清晰，依赖关系如下：\n\n```mermaid\ngraph TD\n    subgraph 数据源层\n        OBS[Obsidian Vault]\n        LOG[Logseq Graph]\n        ROAM[Roam Research]\n        NOTION[Notion Export]\n        CONFL[Confluence]\n        EMAIL[Email .mbox]\n        CAL[Calendar .ics]\n    end\n\n    subgraph 连接器层\n        OBS_C[ObsidianConnector]\n        LOG_C[LogseqConnector]\n        ROAM_C[RoamConnector]\n        NOTION_C[NotionParser]\n        CONFL_C[ConfluenceConnector]\n    end\n\n    subgraph 解析层\n        MARKDOWN[MarkdownParser]\n        OBS_P[ObsidianParser]\n        HTML_P[NotionHTMLParser]\n    end\n\n    subgraph 分块层\n        MD_CHUNK[MarkdownChunker]\n        REC_CHUNK[RecursiveChunker]\n    end\n\n    subgraph 存储层\n        SQLite[(SQLite 元数据库)]\n        QDRANT[(Qdrant 向量库)]\n        CHROMS[Chroma 向量库]\n    end\n\n    subgraph 索引层\n        IDX[FileIndexer]\n        EMB[EmbeddingProvider]\n    end\n\n    subgraph 服务层\n        API[FastAPI MCP Server]\n        DASH[Dashboard Server]\n        HEALTH[Health Server]\n        MCP[MCP Tools]\n    end\n\n    OBS --> OBS_C\n    LOG --> LOG_C\n    ROAM --> ROAM_C\n    NOTION --> NOTION_C\n    CONFL --> CONFL_C\n\n    OBS_C --> OBS_P\n    LOG_C --> MARKDOWN\n    ROAM_C --> MARKDOWN\n    NOTION_C --> HTML_P\n\n    OBS_P --> MD_CHUNK\n    HTML_P --> MD_CHUNK\n    MARKDOWN --> REC_CHUNK\n\n    MD_CHUNK --> IDX\n    REC_CHUNK --> IDX\n    IDX --> EMB\n    EMB --> QDRANT\n    EMB --> CHROMS\n    IDX --> SQLite\n\n    SQLite --> API\n    QDRANT --> API\n    CHROMS --> API\n    API --> MCP\n    API --> DASH\n    API --> HEALTH\n```\n\n**资料来源**：[ARCHITECTURE.md](https://github.com/kilhubprojects/memory-mesh/blob/main/ARCHITECTURE.md)\n\n## 核心组件\n\n### 1. 连接器层（Connectors）\n\n连接器负责从各类外部数据源批量读取文档，统一输出为 `ParsedDocument` 对象。各连接器支持的平台如下：\n\n| 连接器 | 配置类 | 数据格式 | 特性 |\n|--------|--------|----------|------|\n| `ObsidianConnector` | `ObsidianSourceConfig` | Markdown | 解析 YAML frontmatter、`[[wikilinks]]` |\n| `LogseqConnector` | `LogseqConfig` | Markdown | 处理 `((uuid))` 块引用、`{{embed}}` 嵌入、`key:: value` 属性 |\n| `RoamConnector` | `RoamConfig` | JSON | 递归展平嵌套块、清除 `{{[[...]]}}` 模板语法 |\n| `NotionParser` | `NotionSourceConfig` | HTML 导出 | 使用标准库 `html.parser` 解析 |\n| `ConfluenceConnector` | `ConfluenceConfig` | REST API | HTTP Basic 认证、分页拉取 |\n| `EmailParser` | `EmailSourceConfig` | .mbox | 偏好 `text/plain`，回退到 stripped HTML |\n| `CalendarParser` | `CalendarSourceConfig` | .ics | 提取 VEVENT 摘要、时间、地点 |\n\n**资料来源**：[src/memorymesh/connectors/logseq_connector.py:1-80](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\n\n### 2. 解析层（Parsers）\n\n解析器将原始文件内容转换为结构化的 `ParsedDocument`，提取纯文本与元数据。\n\n#### Obsidian 解析器\n\n`ObsidianParser` 专门处理 Obsidian 格式的 Markdown 文件：\n\n- **YAML frontmatter 提取**：匹配 `---` 分隔符之间的内容，解析 `tags`、`aliases`、`created`、`modified` 字段\n- **Wikilink 提取**：正则 `_WIKILINK_RE = r\"(?<!!)\\[\\[([^\\[\\]|#]+?)(?:\\|[^\\[\\]]*?)?\\]\\]\"` 捕获双向链接目标\n- **过滤嵌入图片**：`![[img]]` 格式被排除在 backlinks 之外\n\n```python\n_WIKILINK_RE = re.compile(r\"(?<!!)\\[\\[([^\\[\\]|#]+?)(?:\\|[^\\[\\]]*?)?\\]\\]\")\n```\n\n**资料来源**：[src/memorymesh/parsing/obsidian_parser.py:20-30](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/obsidian_parser.py)\n\n#### Logseq 解析器\n\n`LogseqConnector` 内置解析逻辑，处理 Logseq 特有语法：\n\n| 语法模式 | 正则 | 转换结果 |\n|----------|------|----------|\n| 块引用 | `\\(\\([0-9a-f-]{36}\\)\\)` | `[block]` |\n| 嵌入 | `\\{\\{embed \\[\\[([^\\]]+)\\]\\]\\}\\}` | `[embed: Page]` |\n| 查询块 | `\\{\\{query[^}]*\\}\\}` | 整块移除 |\n| 属性行 | `^([\\w-]+)::\\s*(.+)$` | 存入 metadata |\n\n**资料来源**：[src/memorymesh/connectors/logseq_connector.py:40-50](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\n\n### 3. 分块层（Chunking）\n\n分块策略决定了向量检索的粒度。MemoryMesh 支持以下分块器：\n\n| 分块器 | 策略 | 配置参数 |\n|--------|------|----------|\n| `RecursiveChunker` | 递归字符拆分 | `chunk_size=800`, `chunk_overlap=50` |\n| `MarkdownChunker` | 按 ATX 标题（`#`, `##` 等）切分 | `max_chunk_size=800` |\n\n`MarkdownChunker` 首先按标题分割文档，超出 `max_chunk_size` 的节交给 `RecursiveChunker` 进一步拆分，并保留 `heading_path` 元数据用于精确定位。\n\n**资料来源**：[src/memorymesh/chunking/markdown.py:1-50](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/markdown.py)\n\n### 4. 存储层（Storage）\n\n#### 元数据存储（SQLite）\n\n`FileRepository` 负责管理 SQLite 数据库中的以下表：\n\n- `files`：文件记录，包含路径、SHA-256、修改时间、块数、索引状态等\n- `sources`：数据源配置\n- `index_state`：索引状态追踪\n\n文件记录使用 `ON CONFLICT(path) DO UPDATE` 实现 upsert 语义，保证幂等性：\n\n```sql\nINSERT INTO files\n    (path, source_name, sha256, mtime, size_bytes, file_type,\n     n_chunks, status, error_message, indexed_at, embedding_model_id)\nVALUES (...)\nON CONFLICT(path) DO UPDATE SET\n    source_name = excluded.source_name,\n    sha256 = excluded.sha256,\n    ...\n```\n\n**资料来源**：[src/memorymesh/storage/file_repository.py:15-35](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/storage/file_repository.py)\n\n#### 向量存储\n\nMemoryMesh 支持多种向量数据库作为后端：\n\n| 向量库 | 配置键 | 说明 |\n|--------|--------|------|\n| Qdrant | `vector_store.type: qdrant` | 高性能向量检索 |\n| Chroma | `vector_store.type: chroma` | 轻量级本地向量库 |\n\n向量由 `EmbeddingProvider` 生成，支持 Ollama 本地模型推理。\n\n### 5. 索引层（Indexer）\n\n`FileIndexer` 是索引流程的核心编排器，其主要职责：\n\n```mermaid\ngraph LR\n    A[文件路径] --> B{文件类型判断}\n    B -->|Markdown| C[MarkdownChunker]\n    B -->|其他| D[TextParser]\n    C --> E[RecursiveChunker]\n    D --> E\n    E --> F[EmbeddingProvider]\n    F --> G[向量写入 Qdrant/Chroma]\n    E --> H[Chunk 列表]\n    H --> I[FileRepository upsert]\n```\n\n索引过程中：\n1. 根据文件扩展名选择对应 Parser\n2. Parser 输出 `ParsedDocument`（含纯文本与元数据）\n3. Chunker 将文档切分为 `Chunk` 列表\n4. `EmbeddingProvider` 为每个 chunk 生成向量\n5. 向量写入向量库，元数据写入 SQLite\n\n**资料来源**：[src/memorymesh/indexer/file_indexer.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/indexer/file_indexer.py)\n\n### 6. 服务层（Server）\n\n#### MCP Server\n\nMemoryMesh 通过 FastMCP 暴露 MCP（Model Context Protocol）工具，提供以下能力：\n\n| MCP 工具 | 功能描述 |\n|----------|----------|\n| `search_memory` | 混合检索：向量相似度 + 关键词 |\n| `ask_memory` | RAG 问答：检索 → 上下文组装 → Ollama 生成 |\n| `pin_memory` | 将 chunk 钉住防止遗忘衰减 |\n| `forget_memory` | 抑制或冷却指定 chunk |\n| `get_memory_tier` | 查询 chunk 所在记忆层级 |\n\n所有工具均通过 `auth_guard.py` 中的 `check_access()` 进行权限校验。\n\n**资料来源**：[src/memorymesh/server/tools/forget_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/forget_memory.py)\n\n#### Dashboard Server\n\n基于 FastAPI + HTMX 的 Web 界面，运行在 `:8767` 端口：\n\n| 路由 | 功能 |\n|------|------|\n| `/` | 数据源概览 |\n| `/search` | 检索界面 |\n| `/tiers` | 记忆层级分布统计 |\n| `/entities` | 提取的实体列表 |\n| `/timeline` | 情景记忆时间线 |\n| `/graph-ui` | 知识图谱可视化 |\n\n**资料来源**：[src/memorymesh/server/dashboard.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/dashboard.py)\n\n#### Health Server\n\n轻量级健康检查端点，运行在 `:8766` 端口，用于进程监控与外部探测。\n\n## 关键数据模型\n\n### ParsedDocument\n\n```python\nclass ParsedDocument(BaseModel):\n    path: Path\n    text: str\n    file_type: str\n    encoding: str = \"utf-8\"\n    metadata: dict[str, object] = Field(default_factory=dict)\n```\n\n### Chunk\n\n```python\nclass Chunk(BaseModel):\n    path: Path\n    chunk_index: int\n    text: str\n    start_char: int\n    end_char: int\n    file_type: str = \"\"\n    metadata: ChunkMetadata = Field(default_factory=ChunkMetadata)\n```\n\n**资料来源**：[src/memorymesh/core/models/chunk.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/chunk.py)\n\n## 配置架构\n\nMemoryMesh 使用 YAML 配置文件管理所有组件行为，主要配置节点：\n\n```yaml\nsources:                    # 数据源列表\n  - type: obsidian\n    path: ~/Vault\n  - type: logseq\n    vault_path: ~/Logseq/my-graph\n\nvector_store:\n  type: qdrant              # 或 chroma\n  path: ~/.memorymesh/qdrant\n\nmemory:\n  tiers:\n    enabled: true\n    strategy: importance_based\n  forgetting:\n    enabled: true\n    decay_rate: 0.95\n  episodic:\n    enabled: true\n\nentity_extraction:\n  enabled: true\n  ollama_url: http://localhost:11434\n\nauth:\n  enabled: false            # 默认关闭\n```\n\n## 记忆层级系统\n\nMemoryMesh 引入了基于重要性的记忆层级管理：\n\n```mermaid\ngraph TD\n    HOT[热记忆 Hot] --> WARM[温记忆 Warm]\n    WARM --> COLD[冷记忆 Cold]\n    COLD --> ARCHIVE[归档 Archive]\n\n    style HOT fill:#ff6b6b\n    style WARM fill:#feca57\n    style COLD fill:#54a0ff\n    style ARCHIVE fill:#576574\n```\n\n| 层级 | 用途 | 衰减策略 |\n|------|------|----------|\n| Hot | 高频访问、钉住内容 | 不衰减 |\n| Warm | 最近访问 | 轻量衰减 |\n| Cold | 长期未访问 | 快速衰减 |\n| Archive | 极低相关性 | 可选自动清理 |\n\n`TieredMemoryManager` 根据访问频率与用户显式操作动态调整 chunk 所在层级。\n\n## 认证与权限\n\n`auth_guard.py` 提供统一的权限检查接口：\n\n```python\ncheck_access(ctx: AppContext, action: str, source: str | None) -> bool\n```\n\n支持的权限操作：\n- `read_source`：读取指定数据源\n- `write_source`：修改指定数据源\n- `admin`：管理功能\n\n当 `auth.enabled: false`（默认值）时，所有权限检查自动放行。\n\n## 工作流程总览\n\n```mermaid\nsequenceDiagram\n    participant CLI as CLI (start)\n    participant CTX as AppContext\n    participant CONN as Connectors\n    participant IDX as FileIndexer\n    participant EMB as EmbeddingProvider\n    participant VDB as Vector Store\n    participant SQL as SQLite\n\n    CLI->>CTX: 初始化配置\n    CTX->>CONN: 创建连接器实例\n    loop 每次索引周期\n        CONN->>CONN: fetch_documents()\n        CONN-->>IDX: ParsedDocument stream\n        loop 每个文档\n            IDX->>IDX: parse() → ParsedDocument\n            IDX->>IDX: chunk() → Chunk list\n            IDX->>EMB: embed(chunks)\n            EMB-->>IDX: ChunkWithEmbedding list\n            IDX->>VDB: upsert(embeddings)\n            IDX->>SQL: upsert(FileRecord)\n        end\n    end\n    CLI->>CTX: 启动 MCP Server\n    CTX->>CTX: 注册 MCP 工具\n    Note over CTX: Dashboard :8767, Health :8766\n```\n\n## 扩展机制\n\nMemoryMesh 设计支持以下扩展点：\n\n1. **自定义 Parser**：继承 `Parser` 基类，注册到 `source.type` 映射\n2. **自定义 ChunkStrategy**：实现 `Chunker` 接口\n3. **自定义 VectorStore**：实现 `VectorStore` 接口，适配新的向量数据库\n4. **自定义 Connector**：实现 `Connector` 接口，从新平台拉取数据\n\n## 技术栈总结\n\n| 层级 | 技术选型 |\n|------|----------|\n| 核心框架 | Python 3.11+, Pydantic |\n| Web 框架 | FastAPI, Starlette |\n| 界面 | HTMX, 原生 HTML/CSS |\n| 向量库 | Qdrant / Chroma |\n| 元数据 | SQLite |\n| 本地推理 | Ollama |\n| 协议 | MCP (FastMCP) |\n| 日志 | Loguru |\n| 配置 | YAML + Pydantic ConfigDict |\n\n所有数据默认存储在 `~/.memorymesh/` 目录下，保持完全的本地化与隐私保护。\n\n---\n\n<a id='page-indexing-pipeline'></a>\n\n## 索引管道\n\n### 相关页面\n\n相关主题：[系统架构](#page-architecture), [文件解析器](#page-parsers), [文本分块策略](#page-chunkers), [搜索引擎](#page-search-engine)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/indexer/file_indexer.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/indexer/file_indexer.py)\n- [src/memorymesh/indexer/watcher.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/indexer/watcher.py)\n- [src/memorymesh/parsing/registry.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/registry.py)\n- [src/memorymesh/embeddings/registry.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/embeddings/registry.py)\n- [src/memorymesh/storage/vector_store.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/storage/vector_store.py)\n- [src/memorymesh/storage/bm25_index.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/storage/bm25_index.py)\n</details>\n\n# 索引管道\n\n索引管道是 MemoryMesh 的核心子系统，负责将各种来源的文档转换为可搜索的向量和全文索引数据。本页面详细介绍索引管道的架构设计、数据流、核心组件及其交互方式。\n\n## 架构概述\n\n索引管道采用模块化设计，主要包含以下处理阶段：\n\n```mermaid\ngraph TD\n    A[文档源] --> B[解析器 Registry]\n    B --> C[解析器 Parser]\n    C --> D[ParsedDocument]\n    D --> E[分块器 Chunker]\n    E --> F[Chunk 列表]\n    F --> G[嵌入向量生成]\n    G --> H[向量存储]\n    G --> I[BM25 索引]\n    H --> J[元数据存储]\n    I --> J\n```\n\n管道支持多种文档格式，包括本地 Markdown、Obsidian 笔记、Notion 导出、Roam Research、Logseq、Confluence 以及 Email 和日历等。资料来源：[src/memorymesh/parsing/obsidian_parser.py]()、[src/memorymesh/parsing/notion_parser.py]()、[src/memorymesh/connectors/logseq_connector.py]()、[src/memorymesh/connectors/roam_connector.py]()、[src/memorymesh/connectors/confluence_connector.py]()\n\n## 核心处理流程\n\n### 1. 文档解析阶段\n\n解析器注册表 (`ParserRegistry`) 根据文件类型和来源配置选择合适的解析器。每种解析器负责将特定格式的文档转换为统一的 `ParsedDocument` 数据结构。\n\n支持的解析器类型：\n\n| 解析器 | 文件类型 | 特殊功能 |\n|--------|----------|----------|\n| MarkdownParser | .md, .mdx, .markdown | 基础解析 |\n| ObsidianParser | .md | YAML frontmatter 提取、wikilink 解析 |\n| NotionParser | .html, .htm | Notion 导出格式处理 |\n| LogseqConnector | .md | 属性行解析、block 引用处理 |\n| RoamConnector | JSON | 递归 block 扁平化 |\n| ConfluenceConnector | API | HTML 内容提取 |\n\n资料来源：[src/memorymesh/parsing/registry.py]()\n\n`ParsedDocument` 模型包含以下关键字段：\n\n```python\npath: Path\ntext: str\nfile_type: str\nencoding: str\nmetadata: dict[str, object]  # 包含 frontmatter、tags、aliases 等\n```\n\n资料来源：[src/memorymesh/core/models/chunk.py]()\n\n### 2. 文本分块阶段\n\n分块器将长文档拆分为适合嵌入的段落。每个 `Chunk` 对象包含文本内容、字符位置信息和元数据。\n\n| 分块器 | 适用场景 | 分块策略 |\n|--------|----------|----------|\n| MarkdownChunker | Markdown 文档 | 按 ATX 标题层级切分 |\n| CodeChunker | 源代码文件 | 按函数/类定义节点切分 |\n| RecursiveChunker | 通用文本 | 递归字符级切分 |\n\nMarkdownChunker 特别维护 `heading_path` 元数据字段，记录文档中的完整标题路径，便于精确定位搜索结果。资料来源：[src/memorymesh/chunking/markdown.py]()\n\nCodeChunker 使用 AST 解析提取函数名、类名和语言类型，为代码搜索提供语义级支持。资料来源：[src/memorymesh/chunking/code.py]()\n\n### 3. 向量嵌入阶段\n\n嵌入向量生成器将文本块转换为高维向量表示，用于语义相似度搜索。嵌入提供者通过注册表统一管理，支持配置不同的嵌入模型。\n\n```mermaid\nsequenceDiagram\n    participant C as Chunk\n    participant E as EmbeddingProvider\n    participant V as VectorStore\n    participant M as MetadataStore\n    \n    C->>E: 批量生成嵌入向量\n    E-->>C: embedding: list[float]\n    C->>V: 存储向量 + 元数据\n    C->>M: 创建 FileRecord\n```\n\n资料来源：[src/memorymesh/indexer/file_indexer.py]()\n\n### 4. 混合索引阶段\n\nMemoryMesh 采用混合搜索策略，同时维护向量索引和 BM25 全文索引。\n\n| 索引类型 | 用途 | 存储位置 |\n|----------|------|----------|\n| 向量索引 | 语义相似度搜索 | VectorStore |\n| BM25 索引 | 关键词精确匹配 | BM25Index |\n\nBM25 索引器构建倒排索引，支持按词频和文档频率计算相关性评分。资料来源：[src/memorymesh/storage/bm25_index.py]()\n\n向量存储使用配置的向量数据库，支持多种后端实现。资料来源：[src/memorymesh/storage/vector_store.py]()\n\n## FileIndexer 核心组件\n\n`FileIndexer` 是索引管道的核心编排器，协调各子系统的协作。\n\n### 主要方法\n\n| 方法 | 职责 |\n|------|------|\n| `index_file(path)` | 单文件索引入口 |\n| `index_directory(root, ...)` | 目录批量索引 |\n| `process_document(doc, path, source_name)` | 文档处理流水线 |\n\n资料来源：[src/memorymesh/indexer/file_indexer.py]()\n\n### 索引结果记录\n\n索引完成后，系统创建 `FileRecord` 记录文件状态：\n\n```python\nFileRecord(\n    path=str(path),\n    source_name=source_name,\n    sha256=current_hash,        # 文件内容哈希\n    mtime=stat.st_mtime,        # 修改时间\n    size_bytes=stat.st_size,    # 文件大小\n    file_type=ext,              # 文件类型\n    n_chunks=len(chunks),       # 分块数量\n    status=\"indexed\",           # 索引状态\n    indexed_at=time.time(),     # 索引时间戳\n    embedding_model_id=model_id # 嵌入模型标识\n)\n```\n\n资料来源：[src/memorymesh/indexer/file_indexer.py]()、[src/memorymesh/core/models/chunk.py]()\n\n### 增量索引机制\n\n系统通过 SHA-256 哈希和 mtime 比对检测文件变化，仅对变更文件重新索引：\n\n```python\ncurrent_hash = hashlib.sha256(content).hexdigest()\nif current_hash != existing_file.sha256:\n    # 重新索引\n```\n\n资料来源：[src/memorymesh/indexer/file_indexer.py]()\n\n## 监视器组件\n\n`FileWatcher` 组件监听文件系统变化，触发增量索引。\n\n```mermaid\ngraph LR\n    A[文件系统事件] --> B{事件类型}\n    B -->|创建/修改| C[触发索引]\n    B -->|删除| D[标记文件已删除]\n    B -->|重命名| E[更新文件路径]\n```\n\n资料来源：[src/memorymesh/indexer/watcher.py]()\n\n| 功能 | 说明 |\n|------|------|\n| 增量更新 | 仅索引变更文件 |\n| 软删除处理 | 标记而非立即删除 |\n| 防抖机制 | 避免频繁触发 |\n\n## 配置选项\n\n### IndexingConfig 主要字段\n\n| 字段 | 类型 | 默认值 | 说明 |\n|------|------|--------|------|\n| `chunk_size` | int | 800 | 分块目标字符数 |\n| `chunk_overlap` | int | 50 | 分块重叠字符数 |\n| `generate_summaries` | bool | False | 是否生成摘要块 |\n| `extract_entities` | bool | True | 是否提取实体 |\n\n### EmbeddingConfig 主要字段\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `provider` | str | 嵌入提供者名称 |\n| `model_id` | str | 模型标识符 |\n| `batch_size` | int | 批处理大小 |\n| `dimensions` | int | 向量维度 |\n\n资料来源：[src/memorymesh/embeddings/registry.py]()\n\n## 错误处理\n\n索引管道内置完善的错误处理机制：\n\n| 错误类型 | 处理策略 | 状态记录 |\n|----------|----------|----------|\n| 解析错误 | 返回错误文档，记录到 metadata | `parse_error` |\n| 编码错误 | 使用 fallback 编码或跳过 | `parse_error` |\n| 嵌入失败 | 使用 fallback 提供者 | `index_error` |\n| 存储错误 | 回滚事务，记录错误信息 | `index_error` |\n\n`FileRecord` 的 `status` 字段可能值：`indexed`、`parse_error`、`unsupported`、`deleted`、`pending_reindex`。资料来源：[src/memorymesh/core/models/chunk.py]()\n\n## 数据流总结\n\n```\nSource File → Parser → ParsedDocument → Chunker → Chunks\n                                                      ↓\n                                    ┌─────────────────┴─────────────────┐\n                                    ↓                                   ↓\n                            EmbeddingProvider                  BM25Indexer\n                                    ↓                                   ↓\n                              VectorStore                         BM25Index\n                                    └─────────────────┬─────────────────┘\n                                                      ↓\n                                              MetadataStore\n                                              (FileRecord)\n```\n\n索引管道通过模块化设计实现了灵活的文档处理能力，支持多种数据源的统一索引，并提供向量和全文双重搜索能力，满足不同场景的检索需求。\n\n---\n\n<a id='page-parsers'></a>\n\n## 文件解析器\n\n### 相关页面\n\n相关主题：[索引管道](#page-indexing-pipeline), [文本分块策略](#page-chunkers)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/parsing/base.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/base.py)\n- [src/memorymesh/parsing/markdown.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/markdown.py)\n- [src/memorymesh/parsing/obsidian_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/obsidian_parser.py)\n- [src/memorymesh/parsing/notion_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/notion_parser.py)\n</details>\n\n# 文件解析器\n\n## 概述\n\n文件解析器（Parser）是 MemoryMesh 索引管道中的第一环，负责将各种来源的原始文件转换为统一的 `ParsedDocument` 数据结构。每个解析器专注于特定的文件格式或数据源，提取文本内容和元数据，为后续的分块（Chunking）和向量化（Embedding）做准备。\n\n解析器采用**策略模式**，通过文件扩展名和源类型自动选择合适的解析器实现。系统内置了针对 Markdown、Obsidian、Notion、PDF、DOCX、Email 等格式的专业解析器，同时也支持通过扩展机制接入新的数据源。\n\n资料来源：[src/memorymesh/parsing/base.py]()\n\n## 架构设计\n\n### 解析器基类\n\n所有解析器都继承自 `Parser` 基类，定义统一接口：\n\n```python\nclass Parser(ABC):\n    @property\n    @abstractmethod\n    def supported_extensions(self) -> frozenset[str]:\n        \"\"\"返回解析器支持的文件扩展名集合\"\"\"\n        ...\n\n    @abstractmethod\n    def parse(self, path: Path) -> ParsedDocument:\n        \"\"\"解析指定路径的文件，返回 ParsedDocument\"\"\"\n        ...\n```\n\n资料来源：[src/memorymesh/parsing/base.py]()\n\n### 解析流程\n\n```mermaid\ngraph TD\n    A[原始文件] --> B{文件类型检测}\n    B -->|Markdown .md| C[MarkdownParser]\n    B -->|Obsidian .md| D[ObsidianParser]\n    B -->|Notion .html| E[NotionParser]\n    B -->|PDF .pdf| F[PDFParser]\n    B -->|DOCX .docx| G[DOCXParser]\n    B -->|Email .eml/.msg| H[EmailParser]\n    C --> I[ParsedDocument]\n    D --> I\n    E --> I\n    F --> I\n    G --> I\n    H --> I\n```\n\n### ParsedDocument 数据模型\n\n解析结果封装在 `ParsedDocument` 模型中：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `path` | `Path` | 文件绝对路径 |\n| `text` | `str` | 提取的纯文本内容 |\n| `file_type` | `str` | 规范化文件类型标识 |\n| `encoding` | `str` | 源文件编码 |\n| `metadata` | `dict` | 格式特定的元数据 |\n\n资料来源：[src/memorymesh/core/models/__init__.py]()\n\n## 内置解析器\n\n### Markdown 解析器\n\n**文件路径**: `src/memorymesh/parsing/markdown.py`\n\n`MarkdownParser` 是标准 Markdown 文件的解析器，使用与文本解析器相同的编码容错读取机制。它将解析结果标记为 `file_type=\".md\"`，使后续分块层能够选择标题感知的分割器。\n\n```python\nclass MarkdownParser(Parser):\n    @property\n    def supported_extensions(self) -> frozenset[str]:\n        return frozenset({\".md\", \".mdx\", \".markdown\"})\n\n    def parse(self, path: Path) -> ParsedDocument:\n        text, encoding, error = _read_with_fallback(path)\n        meta: dict[str, object] = {}\n        if error:\n            meta[\"error\"] = error\n        return ParsedDocument(\n            path=path,\n            text=text,\n            file_type=\".md\",\n            encoding=encoding,\n            metadata=meta,\n        )\n```\n\n资料来源：[src/memorymesh/parsing/markdown.py]()\n\n### Obsidian 解析器\n\n**文件路径**: `src/memorymesh/parsing/obsidian_parser.py`\n\n`ObsidianParser` 继承自 `MarkdownParser`，增加了对 Obsidian 特有语法的支持：\n\n| 功能 | 说明 |\n|------|------|\n| YAML 前置元数据 | 提取 `---` 分隔符之间的内容 |\n| Wikilink 反向链接 | 识别 `[[链接]]` 和 `[[链接\\|别名]]` 模式 |\n| 嵌入图片过滤 | 排除 `![[图片]]` 等嵌入媒体 |\n| 标签提取 | 解析 `tags:` 字段和内联 `#标签` 语法 |\n\n```python\n# YAML 前置元数据正则\n_FRONTMATTER_RE = re.compile(\n    r\"^---\\r?\\n(.*?)\\r?\\n(?:---|\\.\\.\\.)(?:\\r?\\n|$)\",\n    re.DOTALL,\n)\n\n# Wikilink 提取正则（排除 ![[ 嵌入]]）\n_WIKILINK_RE = re.compile(r\"(?<!!)\\[\\[([^\\[\\]|#]+?)(?:\\|[^\\[\\]]*?)?\\]\\]\")\n```\n\n提取的元数据字段：\n\n```python\nmeta[\"frontmatter\"] = fm_data          # YAML 字段字典\nmeta[\"tags\"] = tags                     # 标签列表\nmeta[\"aliases\"] = aliases               # 别名列表\nmeta[\"created\"] = created              # 创建时间\nmeta[\"modified\"] = modified             # 修改时间\nmeta[\"backlinks\"] = wikilink_targets    # Wikilink 目标列表\n```\n\n资料来源：[src/memorymesh/parsing/obsidian_parser.py]()\n\n### Notion 解析器\n\n**文件路径**: `src/memorymesh/parsing/notion_parser.py`\n\n`NotionParser` 专门处理 Notion HTML 导出格式，仅依赖标准库 `html.parser`，无需外部依赖。\n\n```python\nclass _NotionHTMLParser(HTMLParser):\n    \"\"\"SAX 风格解析器，收集纯文本和元数据\"\"\"\n    \n    _SKIP_TAGS: frozenset[str] = frozenset(\n        {\"style\", \"script\", \"head\", \"meta\", \"link\"}\n    )\n```\n\n解析能力：\n\n- 提取 `<title>` 标签内容\n- 提取 `<h1>` 可见页面标题\n- 收集 `data-type` 属性值（数据库属性类型）\n- 剥离所有 HTML 标签获取纯文本\n- 从文件名提取 Notion 页面 UUID\n\n```python\n_UUID_FILENAME_RE = re.compile(\n    r\"([0-9a-f]{8}(?:[0-9a-f]{4}){3}[0-9a-f]{12})(?:\\s|\\.|$)\",\n    re.IGNORECASE,\n)\n```\n\nNotion 解析器返回的元数据包含：\n\n| 字段 | 说明 |\n|------|------|\n| `notion_id` | 页面 UUID |\n| `database_name` | 所属数据库名称 |\n| `title` | 页面标题 |\n| `db_properties` | 数据库属性列表 |\n\n资料来源：[src/memorymesh/parsing/notion_parser.py]()\n\n## 支持的文件格式\n\n| 解析器 | 扩展名 | 源类型 |\n|--------|--------|--------|\n| `MarkdownParser` | `.md`, `.mdx`, `.markdown` | 通用 Markdown |\n| `ObsidianParser` | `.md` | `obsidian` |\n| `NotionParser` | `.html`, `.htm` | `notion` |\n| `PDFParser` | `.pdf` | 通用 |\n| `DOCXParser` | `.docx` | 通用 |\n| `EmailParser` | `.eml`, `.msg` | 通用 |\n\n## 解析模式\n\n### 编码容错读取\n\n解析器使用 `_read_with_fallback` 函数处理各种文件编码：\n\n```python\ndef _read_with_fallback(path: Path) -> tuple[str, str, str | None]:\n    \"\"\"尝试 UTF-8 读取，失败时回退到 latin-1\"\"\"\n```\n\n该函数按顺序尝试：\n1. UTF-8 编码\n2. 回退到 `latin-1` 编码\n3. 返回错误信息而非抛出异常\n\n资料来源：[src/memorymesh/parsing/text.py]()\n\n### 错误处理\n\n所有解析器遵循统一的错误处理策略：\n\n```python\nif error:\n    meta[\"error\"] = error\n    return ParsedDocument(\n        path=path,\n        text=\"\",\n        file_type=file_type,\n        encoding=encoding,\n        metadata=meta,\n    )\n```\n\n解析失败时返回空的 `text` 内容，但保留 `error` 字段供诊断使用。\n\n## 与连接器的协作\n\n解析器不仅处理本地文件，还被**连接器（Connector）**模块间接调用：\n\n```mermaid\ngraph LR\n    A[连接器] -->|fetch_documents| B[ParsedDocument]\n    B --> C[索引器]\n    C --> D[分块]\n    D --> E[向量化]\n    E --> F[向量数据库]\n```\n\n连接器处理远程数据获取和格式转换，然后使用解析器或解析后的格式输出 `ParsedDocument`：\n\n- **RoamConnector** - 解析 Roam Research JSON 导出\n- **LogseqConnector** - 处理 Logseq Markdown 文件\n- **NotionConnector** - 调用 Notion API 获取页面\n- **ConfluenceConnector** - 从 Confluence REST API 获取页面\n\n资料来源：[src/memorymesh/connectors/roam_connector.py]()\n资料来源：[src/memorymesh/connectors/logseq_connector.py]()\n资料来源：[src/memorymesh/connectors/notion_connector.py]()\n资料来源：[src/memorymesh/connectors/confluence_connector.py]()\n\n## 使用示例\n\n### 直接使用解析器\n\n```python\nfrom pathlib import Path\nfrom memorymesh.parsing.obsidian_parser import ObsidianParser\n\nparser = ObsidianParser()\ndoc = parser.parse(Path(\"/vault/my-note.md\"))\n\nprint(f\"文本长度: {len(doc.text)}\")\nprint(f\"标签: {doc.metadata.get('tags')}\")\nprint(f\"反向链接: {doc.metadata.get('backlinks')}\")\n```\n\n### 配置源类型自动选择\n\n当 `source.type` 配置为 `obsidian` 时，系统自动注册 `ObsidianParser` 处理 `.md` 文件；通用 Markdown 源则使用标准 `MarkdownParser`。\n\n## 扩展新的解析器\n\n实现自定义解析器需继承 `Parser` 基类：\n\n```python\nfrom memorymesh.parsing.base import Parser\nfrom memorymesh.core.models import ParsedDocument\n\nclass CustomParser(Parser):\n    @property\n    def supported_extensions(self) -> frozenset[str]:\n        return frozenset({\".custom\"})\n    \n    def parse(self, path: Path) -> ParsedDocument:\n        # 实现解析逻辑\n        return ParsedDocument(\n            path=path,\n            text=processed_text,\n            file_type=\".custom\",\n            metadata={\"source\": \"custom\"},\n        )\n```\n\n## 总结\n\n文件解析器模块是 MemoryMesh 多格式支持的核心，通过统一的 `Parser` 接口和 `ParsedDocument` 数据模型，实现了：\n\n- **格式解耦** - 解析逻辑与索引逻辑分离\n- **自动选择** - 根据扩展名和源类型自动路由\n- **元数据丰富** - 提取格式特定信息供高级检索使用\n- **容错设计** - 编码错误和解析失败不影响整体流程\n\n---\n\n<a id='page-chunkers'></a>\n\n## 文本分块策略\n\n### 相关页面\n\n相关主题：[索引管道](#page-indexing-pipeline), [文件解析器](#page-parsers)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/chunking/base.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/base.py)\n- [src/memorymesh/chunking/recursive.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/recursive.py)\n- [src/memorymesh/chunking/markdown.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/markdown.py)\n- [src/memorymesh/chunking/code.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/code.py)\n- [src/memorymesh/chunking/registry.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/registry.py)\n</details>\n\n# 文本分块策略\n\n## 概述\n\n文本分块策略是 MemoryMesh 项目中用于将大型文档拆分为可管理单元的核心机制。在 RAG（检索增强生成）系统架构中，分块策略直接影响检索质量和生成效果。MemoryMesh 实现了多种专业化的分块器，每种分块器针对特定内容类型进行优化，确保拆分后的文本块（Chunk）既保持语义完整性，又便于后续的向量检索。\n\n系统通过统一的 `Chunk` 数据模型和抽象基类 `Chunker` 接口，支持灵活的扩展机制。文档解析完成后，相应的分块器会根据文件类型自动选择并应用，实现无缝的文档处理流程。\n\n资料来源：[src/memorymesh/chunking/base.py:1-30]()\n\n## 架构设计\n\n### 核心抽象\n\nMemoryMesh 的分块系统采用策略模式设计，核心组件包括：\n\n```mermaid\ngraph TD\n    A[ParsedDocument] --> B[Chunker Registry]\n    B --> C{Markdown?}\n    B --> D{Code?}\n    B --> E{Default?}\n    C --> F[MarkdownChunker]\n    D --> G[CodeChunker]\n    E --> H[RecursiveChunker]\n    F --> I[Chunk List]\n    G --> I\n    H --> I\n```\n\n`Chunker` 抽象基类定义了统一的分块接口，所有具体分块器都必须实现 `chunk(doc: ParsedDocument) -> list[Chunk]` 方法。这种设计允许在运行时根据文件类型动态选择最合适的分块策略。\n\n资料来源：[src/memorymesh/chunking/base.py:12-18]()\n\n### 分块器类型对比\n\n| 分块器 | 适用场景 | 分割依据 | 依赖项 |\n|--------|----------|----------|--------|\n| MarkdownChunker | Markdown 文档 | ATX 标题层级 | 无 |\n| CodeChunker | 源代码文件 | AST 语法树节点 | tree-sitter-languages |\n| RecursiveChunker | 通用文本 | 字符数/段落/句子 | 无 |\n\n资料来源：[src/memorymesh/chunking/registry.py:44-73]()\n\n## Markdown 分块器\n\n### 工作原理\n\n`MarkdownChunker` 基于 ATX 标题语法（`#`、`##`、`###` 等）对文档进行结构化拆分。每个分块包含一个标题及其下方内容，直到遇到同级或更高级别标题为止。\n\n```mermaid\ngraph LR\n    A[\"# 文档标题\"] --> B[\"## 第一章节<br>章节内容...\"]\n    B --> C[\"## 第二章节<br>章节内容...\"]\n    B --> D[\"### 2.1 子章节<br>子内容...\"]\n    D --> C\n```\n\n系统通过正则表达式 `^(#{1,6})\\s+(.*)` 匹配所有标题行，并维护一个 heading_stack（标题栈）来追踪当前章节的层级关系。\n\n资料来源：[src/memorymesh/chunking/markdown.py:1-50]()\n\n### 标题路径元数据\n\n每个 Markdown 分块都包含 `heading_path` 元数据字段，记录从根标题到当前标题的完整路径。例如，对于 `### 2.1 子章节`，其 `heading_path` 为 `[\"文档标题\", \"第一章节\", \"子章节\"]`。这一特性使搜索命中可以精确定位到文档中的具体位置。\n\n资料来源：[src/memorymesh/chunking/markdown.py:80-85]()\n\n### 溢出拆分机制\n\n当单个章节内容超过 `max_chunk_size`（默认 800 字符）时，`MarkdownChunker` 会调用 `RecursiveChunker` 进行递归拆分，确保最终分块大小符合配置要求。\n\n资料来源：[src/memorymesh/chunking/markdown.py:24-27]()\n\n## 代码分块器\n\n### AST 感知分割\n\n`CodeChunker` 使用 tree-sitter 库解析源代码的抽象语法树（AST），在顶级函数和类定义处进行分割。这种分割方式保持了代码结构完整性，便于检索时代码片段的语义理解。\n\n```mermaid\ngraph TD\n    A[源代码文件] --> B[tree-sitter 解析]\n    B --> C[提取顶级节点]\n    C --> D{节点类型?}\n    D -->|function_definition| E[函数分块]\n    D -->|class_definition| F[类分块]\n    D -->|其他| G[残留代码处理]\n    E --> H[Chunk List]\n    F --> H\n    G --> H\n```\n\n资料来源：[src/memorymesh/chunking/code.py:1-60]()\n\n### 支持的编程语言\n\n| 扩展名 | 语言标识 | 扩展名 | 语言标识 |\n|--------|----------|--------|----------|\n| .py | python | .go | go |\n| .js / .jsx | javascript | .rs | rust |\n| .ts / .tsx | typescript / tsx | .rb | ruby |\n| .java | java | .php | php |\n| .c / .h | c | .swift | swift |\n| .cpp / .hpp | cpp | .kt | kotlin |\n| .cs | c_sharp | | |\n\n资料来源：[src/memorymesh/chunking/code.py:16-36]()\n\n### 分割节点类型\n\n代码分块器在以下 AST 节点类型处进行分割：\n\n- `function_definition`\n- `function_declaration`\n- `method_definition`\n- `class_definition`\n- `class_declaration`\n\n资料来源：[src/memorymesh/chunking/code.py:38-45]()\n\n### 元数据标记\n\n每个代码分块包含丰富的元数据：\n\n- `language`：编程语言名称\n- `function_name`：函数名（如适用）\n- `class_name`：所属类名（如适用）\n\n这些元数据使搜索结果可以精确定位到具体的代码符号。\n\n资料来源：[src/memorymesh/chunking/code.py:95-100]()\n\n### 回退机制\n\n当发生以下情况时，`CodeChunker` 自动回退到 `RecursiveChunker`：\n\n- tree-sitter-languages 未安装\n- 不支持当前文件扩展名\n- tree-sitter 运行时错误\n\n资料来源：[src/memorymesh/chunking/code.py:48-55]()\n\n## 递归分块器\n\n### 层级拆分策略\n\n`RecursiveChunker` 采用多层级递归策略，将文本从大到小逐步拆分，直到满足大小约束。\n\n```mermaid\ngraph TD\n    A[完整文本] --> B{是否超过 chunk_size?}\n    B -->|否| Z[直接返回]\n    B -->|是| C[按段落分割]\n    C --> D{段落是否超过限制?}\n    D -->|是| E[按句子分割]\n    E --> F{句子是否超过限制?}\n    F -->|是| G[按字符数硬截断]\n    G --> H[合并重叠分块]\n    D -->|否| H\n    F -->|否| H\n    H --> I[Chunk List]\n```\n\n资料来源：[src/memorymesh/chunking/recursive.py:1-80]()\n\n### 分割层级\n\n分块器按以下顺序尝试拆分：\n\n1. **段落分割**：按双换行符 `\\n\\n` 分割\n2. **句子分割**：按 `. `、`!`、`?` 等标点分割\n3. **字符截断**：按 `chunk_size` 硬截断\n\n每层拆分后，检查子块是否仍超过大小限制，如是则继续下一层拆分。\n\n资料来源：[src/memorymesh/chunking/recursive.py:30-60]()\n\n### 重叠机制\n\n为保持上下文连续性，相邻分块之间存在 `chunk_overlap`（默认 50 字符）的重叠区域。重叠通过向前回溯实现，确保重要内容不会因分割边界而被切断。\n\n资料来源：[src/memorymesh/chunking/recursive.py:62-70]()\n\n## 分块器注册表\n\n### 文件类型选择逻辑\n\n`ChunkerRegistry` 负责根据文件扩展名选择合适的分块器：\n\n```mermaid\ngraph TD\n    A[输入: extension] --> B{是否为 Markdown 扩展名?}\n    B -->|是| C[返回 MarkdownChunker]\n    B -->|否| D{是否为代码扩展名?}\n    D -->|是| E[返回 CodeChunker]\n    D -->|否| F[返回 RecursiveChunker]\n```\n\nMarkdown 扩展名集合：`.md`、`.mdx`、`.markdown`\n\n代码扩展名集合：`.py`、`.js`、`.jsx`、`.ts`、`.tsx`、`.java`、`.c`、`.cpp`、`.h`、`.hpp`、`.cs`、`.go`、`.rs`、`.rb`、`.php`、`.swift`、`.kt`\n\n资料来源：[src/memorymesh/chunking/registry.py:18-28]()\n\n### 获取分块器接口\n\n```python\ndef get_chunker(\n    extension: str,\n    chunking_config: ChunkingConfig | None = None\n) -> Chunker\n```\n\n当 `chunking_config` 为 `None` 时，使用默认配置参数初始化各分块器。\n\n资料来源：[src/memorymesh/chunking/registry.py:30-73]()\n\n## 配置参数\n\n### 分块配置模型\n\n| 配置项 | 类型 | 默认值 | 说明 |\n|--------|------|--------|------|\n| `max_chunk_size` | int | 800 | Markdown 分块器：单个章节最大字符数 |\n| `chunk_size` | int | - | RecursiveChunker：目标分块大小 |\n| `chunk_overlap` | int | 50 | RecursiveChunker：相邻分块重叠字符数 |\n\n资料来源：[src/memorymesh/chunking/markdown.py:48-50]()\n\n### 配置使用示例\n\n```python\nfrom memorymesh.chunking.registry import get_chunker\nfrom memorymesh.core.models import ChunkingConfig, MarkdownChunkingConfig\n\nconfig = ChunkingConfig(\n    markdown=MarkdownChunkingConfig(max_chunk_size=1000),\n    code=CodeChunkingConfig(max_chunk_size=500),\n    default=RecursiveChunkingConfig(chunk_size=300, chunk_overlap=30)\n)\n\nchunker = get_chunker(\".py\", chunking_config=config)\n```\n\n## 数据模型\n\n### Chunk 数据结构\n\n```python\nclass Chunk(BaseModel):\n    path: Path                      # 源文件绝对路径\n    chunk_index: int                # 文件内分块序号\n    text: str                       # 分块文本内容\n    start_char: int                 # 在源文本中的起始字符偏移\n    end_char: int                   # 在源文本中的结束字符偏移\n    file_type: str                  # 文件类型扩展名\n    mtime: float                    # 文件修改时间戳\n    source_root: str                # 来源配置名称\n    metadata: ChunkMetadata         # 结构化元数据\n```\n\n资料来源：[src/memorymesh/core/models/chunk.py:35-55]()\n\n### ChunkMetadata 元数据\n\n```python\nclass ChunkMetadata(BaseModel):\n    heading_path: list[str] = []    # Markdown 标题路径\n    language: str = \"\"              # 代码语言标识\n    function_name: str = \"\"         # 函数名\n    class_name: str = \"\"            # 类名\n```\n\n资料来源：[src/memorymesh/chunking/markdown.py:82-85]() 和 [src/memorymesh/chunking/code.py:95-100]()\n\n### Chunk ID 标识符\n\n每个 Chunk 具有稳定的唯一标识符，格式为 `<path>:<chunk_index>`，便于跨系统引用和去重。\n\n资料来源：[src/memorymesh/core/models/chunk.py:57-59]()\n\n## 最佳实践\n\n### 调整分块大小\n\n| 使用场景 | 推荐配置 |\n|----------|----------|\n| 细粒度检索（如代码搜索） | `max_chunk_size=300-500` |\n| 文档问答 | `max_chunk_size=800-1000` |\n| 长文档摘要 | `max_chunk_size=1500+` |\n\n### 选择分块策略\n\n- **结构化文档**（Markdown）：优先使用 `MarkdownChunker` 保留文档结构\n- **源代码**：使用 `CodeChunker` 保持函数/类完整性\n- **非结构化文本**：使用 `RecursiveChunker` 按语义层级拆分\n\n---\n\n<a id='page-search-engine'></a>\n\n## 搜索引擎\n\n### 相关页面\n\n相关主题：[系统架构](#page-architecture), [结果重排序](#page-reranking), [MCP 工具参考](#page-mcp-tools)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/search/engine.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/engine.py)\n- [src/memorymesh/search/rank_fusion.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/rank_fusion.py)\n- [src/memorymesh/search/query_expander.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/query_expander.py)\n- [src/memorymesh/llm/ollama_client.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/llm/ollama_client.py)\n- [src/memorymesh/server/tools/ask_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/ask_memory.py)\n- [CHANGELOG.md](https://github.com/kilhubprojects/memory-mesh/blob/main/CHANGELOG.md)\n- [src/memorymesh/server/dashboard.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/dashboard.py)\n- [ARCHITECTURE.md](https://github.com/kilhubprojects/memory-mesh/blob/main/ARCHITECTURE.md)\n</details>\n\n# 搜索引擎\n\n## 1. 概述\n\nMemoryMesh 的搜索引擎是一个混合检索系统，支持密集检索（dense retrieval）和稀疏检索（sparse retrieval）两种方式，并提供可选的重排序（reranking）和查询扩展（query expansion）功能。该引擎是整个知识库问答系统的核心，负责从向量数据库中快速定位相关文本块。\n\n搜索引擎的核心职责包括：\n\n- 接收用户查询文本\n- 通过查询扩展生成语义变体\n- 并行执行多种检索策略\n- 使用排名融合（rank fusion）整合多路检索结果\n- 可选地通过 LLM 进行结果重排序\n- 返回排序后的搜索命中列表\n\n资料来源：[CHANGELOG.md]()\n\n## 2. 架构设计\n\n### 2.1 整体架构图\n\n```mermaid\ngraph TD\n    A[用户查询] --> B[查询扩展 QueryExpander]\n    B --> C[生成多个查询变体]\n    C --> D[并行检索 Pipeline]\n    D --> E[密集检索 Dense Retriever]\n    D --> F[稀疏检索 Sparse Retriever]\n    E --> G[排名融合 RankFusion]\n    F --> G\n    G --> H[可选: 重排序 Reranker]\n    H --> I[SearchHit 结果列表]\n    \n    J[Ollama LLM] -.-> H\n    K[向量数据库] -.-> E\n    L[元数据存储] -.-> F\n```\n\n### 2.2 核心组件\n\n| 组件 | 文件路径 | 职责 |\n|------|----------|------|\n| SearchEngine | `search/engine.py` | 主编排引擎，协调整个检索流程 |\n| QueryExpander | `search/query_expander.py` | 查询扩展，生成语义变体 |\n| RankFusion | `search/rank_fusion.py` | 多路结果融合 |\n| OllamaClient | `llm/ollama_client.py` | 本地 LLM 调用接口 |\n| AskMemory | `server/tools/ask_memory.py` | MCP 工具封装 |\n\n资料来源：[CHANGELOG.md]()\n\n## 3. 检索策略\n\n### 3.1 并行变体检索\n\nSearchEngine 使用 `ThreadPoolExecutor` 实现并行检索。针对扩展后的多个查询变体，系统会并发地向向量数据库发起检索请求，最后将所有结果汇总。这一设计显著提升了长查询的检索效率。\n\n```python\n# 伪代码展示并行检索逻辑\ndef _retrieve_single(self, variant_query: str) -> list[SearchHit]:\n    \"\"\"执行单个查询变体的检索\"\"\"\n\ndef _fuse_all(self, all_hits: list[list[SearchHit]]) -> list[SearchHit]:\n    \"\"\"融合多路检索结果\"\"\"\n```\n\n资料来源：[CHANGELOG.md]()\n\n### 3.2 密集检索与稀疏检索\n\n系统支持两种互补的检索模式：\n\n- **密集检索（Dense Retrieval）**：使用文本嵌入模型将查询和文档都编码为向量，在向量空间中进行相似度搜索，适合语义匹配。\n- **稀疏检索（Sparse Retrieval）**：基于关键词的传统 BM25 或类似算法，适合精确术语匹配。\n\n两种检索结果通过排名融合算法整合，兼顾语义理解和精确匹配。\n\n### 3.3 摘要块过滤\n\n系统支持在索引阶段生成摘要块（`chunk_type=\"summary\"`），这些摘要块存储在向量数据库中用于提升抽象语义召回率。但在搜索结果返回时，摘要块会被自动过滤掉，不会直接暴露给用户。\n\n资料来源：[CHANGELOG.md]()\n\n## 4. 查询扩展\n\nQueryExpander 负责将用户原始查询扩展为多个语义变体，以提升检索的召回率。\n\n### 4.1 配置参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `n_lexical_variants` | 生成的词汇变体数量 | 1 |\n| `expansion_model` | 使用的扩展模型 | - |\n\n在最新版本中，`n_lexical_variants` 的默认值从 2 降低到 1，以减少查询噪声。\n\n资料来源：[CHANGELOG.md]()\n\n### 4.2 扩展流程\n\n```mermaid\ngraph LR\n    A[原始查询] --> B[语义分析]\n    B --> C[生成变体1]\n    B --> D[生成变体2]\n    C --> E[合并为查询列表]\n    D --> E\n    E --> F[并行检索]\n```\n\n## 5. 排名融合\n\n当多路检索返回结果后，RankFusion 模块负责将不同检索策略的结果合并为统一的排序列表。\n\n### 5.1 融合策略\n\n融合算法会考虑每个命中结果在不同检索通道中的排名位置，给予排名靠前的结果更高的融合分数。最终返回一个综合排序后的 `SearchHit` 列表。\n\n## 6. 重排序（Reranking）\n\n### 6.1 简介\n\n可选的重排序功能使用 LLM 对初筛结果进行二次排序，以提升结果相关性。\n\n### 6.2 配置参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `top_k_before_rerank` | 重排序前保留的候选结果数 | 35 |\n| `model` | 使用的重排序模型 | - |\n\n该参数默认值从 20 提高到 35，以防止长描述性查询中的相关文件在重排序前被错误排除。\n\n资料来源：[CHANGELOG.md]()\n\n## 7. 搜索工具（Ask Memory MCP）\n\nAsk Memory 是一个 MCP（Model Context Protocol）工具，封装了搜索引擎用于 AI 对话助手的问答场景。\n\n### 7.1 工作流程\n\n```mermaid\ngraph TD\n    A[用户问题] --> B[混合检索]\n    B --> C[上下文组装]\n    C --> D[Ollama Generate]\n    D --> E[返回答案 + 引用来源]\n    \n    F[Ollama 不可用] -.-> G[返回来源列表 + 安装提示]\n    G --> E\n```\n\n### 7.2 返回格式\n\n```python\nclass AskMemoryResponse:\n    answer: str | None       # LLM 生成的回答\n    sources: list[SearchHit] # 搜索命中文档\n    model: str               # 使用的模型名称\n    ollama_available: bool   # Ollama 是否可用\n    hint: str | None         # 仅在不可用时返回\n```\n\n### 7.3 降级策略\n\n当 Ollama 本地 LLM 服务不可用时，系统会优雅降级：返回原始搜索结果列表，并在响应中包含安装提示（hint），确保不会因 LLM 不可用而完全失败。\n\n资料来源：[ARCHITECTURE.md]()\n\n## 8. Web 界面\n\n### 8.1 搜索页面\n\nMemoryMesh 提供基于 FastAPI + HTMX 的 Web 搜索界面，支持用户直接输入查询词进行搜索。搜索结果以 HTML 形式渲染展示。\n\n### 8.2 路由定义\n\n| 路由 | 方法 | 功能 |\n|------|------|------|\n| `/search` | GET/POST | 搜索页面，支持 `mode` 参数（dense/sparse/hybrid） |\n\n```html\n<!-- 搜索表单示例 -->\n<form method=\"get\" action=\"/search\">\n  <input name=\"q\" placeholder=\"输入搜索内容...\">\n  <select name=\"mode\">\n    <option value=\"hybrid\" selected>Hybrid</option>\n    <option value=\"dense\">Dense</option>\n    <option value=\"sparse\">Sparse</option>\n  </select>\n  <button type=\"submit\">Search</button>\n</form>\n```\n\n资料来源：[src/memorymesh/server/dashboard.py]()\n\n## 9. 配置示例\n\n在 `config.yaml` 中配置搜索相关参数：\n\n```yaml\nsearch:\n  embedding_model: sentence-transformers/all-MiniLM-L6-v2\n  dense:\n    top_k: 10\n  sparse:\n    top_k: 10\n  reranker:\n    enabled: true\n    top_k_before_rerank: 35\n  query_expansion:\n    enabled: true\n    n_lexical_variants: 1\n```\n\n## 10. 依赖关系\n\n| 依赖项 | 用途 |\n|--------|------|\n| `sentence-transformers` | 文本嵌入模型 |\n| `faiss` 或 `chromadb` | 向量数据库 |\n| `Ollama` | 本地 LLM 推理 |\n| `fastapi` | Web 服务框架 |\n| `httpx` | HTTP 客户端 |\n\n## 11. 相关文档\n\n- [架构总览](./ARCHITECTURE.md)\n- [配置指南](./CONFIG.md)\n- [API 参考](./API.md)\n- [MCP 工具文档](./MCP_TOOLS.md)\n\n---\n\n<a id='page-reranking'></a>\n\n## 结果重排序\n\n### 相关页面\n\n相关主题：[搜索引擎](#page-search-engine)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/search/reranker.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/reranker.py)\n- [src/memorymesh/core/models/config.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/config.py)\n- [src/memorymesh/search/engine.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/engine.py)\n- [src/memorymesh/search/models.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/models.py)\n- [CHANGELOG.md](https://github.com/kilhubprojects/memory-mesh/blob/main/CHANGELOG.md)\n- [ARCHITECTURE.md](https://github.com/kilhubprojects/memory-mesh/blob/main/ARCHITECTURE.md)\n</details>\n\n# 结果重排序\n\n结果重排序（Result Reranking）是 MemoryMesh 搜索系统中提升检索精度的核心机制。该模块在完成初步检索后，通过交叉编码器（Cross-Encoder）对候选结果进行深度语义相关性评分，从而修正纯向量检索可能产生的排序偏差。\n\n## 工作原理\n\nMemoryMesh 采用典型的两阶段检索架构：**密集检索（Dense Retrieval）** → **结果重排序（Reranking）**。\n\n```mermaid\ngraph TD\n    A[用户查询] --> B[密集检索阶段]\n    B --> C[召回 Top-N 候选结果<br/>top_k_before_rerank]\n    C --> D[重排序阶段]\n    D --> E[交叉编码器评分]\n    E --> F[按相关性重新排序]\n    F --> G[返回 Top-K 最终结果<br/>top_k]\n    C -.->|候选集过大<br/>影响精度| D\n```\n\n第一阶段使用密集向量检索快速从大规模语料中召回候选文档；第二阶段通过语义更精准的交叉编码器对候选集进行细粒度排序，最终输出高相关性的结果列表。\n\n资料来源：[ARCHITECTURE.md:1-50]()\n\n## 配置参数\n\n重排序功能通过 `SearchRerankerConfig` 进行配置，主要参数如下：\n\n| 参数 | 类型 | 默认值 | 说明 |\n|------|------|--------|------|\n| `enabled` | `bool` | `True` | 是否启用重排序 |\n| `model` | `str` | `\"cross-encoder\"` | 交叉编码器模型标识 |\n| `top_k_before_rerank` | `int` | `35` | 重排序前保留的候选结果数量 |\n| `top_k` | `int` | `5` | 最终返回的结果数量 |\n\n> **配置变更历史**：在 v1.2.0 版本中，`top_k_before_rerank` 的默认值从 `20` 提升至 `35`。此调整旨在防止长描述性查询中相关文档在重排序前被过早过滤，从而提升召回率。\n\n资料来源：[src/memorymesh/core/models/config.py:1-100]()\n资料来源：[CHANGELOG.md:1-50]()\n\n## 交叉编码器模型\n\n重排序阶段使用的交叉编码器接收查询与文档对（query-document pair），输出单一相关性分数。相比于双编码器（Bi-Encoder）分别编码查询和文档的方式，交叉编码器能够在注意力机制中直接建模两者的交互关系，从而捕获更精细的语义关联。\n\n```mermaid\ngraph LR\n    subgraph 交叉编码器\n        Q[Query Token序列] -->|拼接| M[联合输入]\n        D[Document Token序列] -->|拼接| M\n        M --> AT[Attention层]\n        AT --> FC[全连接层]\n        FC --> S[相关性分数: 0-1]\n    end\n```\n\n模型输出范围为 0 到 1 的浮点数，其中：\n- `1.0` 表示极高相关性\n- `0.0` 表示完全不相关\n\n资料来源：[src/memorymesh/search/reranker.py:1-80]()\n\n## 搜索流程集成\n\n重排序模块嵌入在 `SearchEngine` 的完整检索管线中：\n\n```mermaid\ngraph TD\n    A[search_query] --> B[QueryExpansion]\n    B --> C[并行向量检索<br/>ThreadPoolExecutor]\n    C --> D[融合多路检索结果]\n    D --> E{top_k_before_rerank<br/>≥ top_k?}\n    E -->|是| F[交叉编码器重排序]\n    F --> G[返回Top-K结果]\n    E -->|否| G\n```\n\n> **并行优化**：`SearchEngine` 已使用 `ThreadPoolExecutor` 实现多路查询变体的并行检索，提升整体响应速度。\n\n资料来源：[src/memorymesh/search/engine.py:1-100]()\n资料来源：[CHANGELOG.md:30-40]()\n\n## 与其他搜索组件的关系\n\n| 组件 | 作用阶段 | 输入 | 输出 |\n|------|----------|------|------|\n| QueryExpansion | 预处理 | 用户原始查询 | 扩展查询变体列表 |\n| EmbeddingProvider | 密集检索 | 查询文本 | 向量表示 |\n| VectorStore | 检索 | 查询向量 | Top-N 候选文档 |\n| **Reranker** | **重排序** | **候选文档 + 查询** | **重排序后的文档列表** |\n| SearchReranker | 最终封装 | 重排序结果 | SearchHit 列表 |\n\n资料来源：[src/memorymesh/search/models.py:1-50]()\n\n## 使用示例\n\n```python\nfrom memorymesh.core.models.config import SearchConfig, SearchRerankerConfig\nfrom memorymesh.search.engine import SearchEngine\n\n# 配置重排序参数\nreranker_cfg = SearchRerankerConfig(\n    enabled=True,\n    top_k_before_rerank=35,\n    top_k=5,\n)\n\nsearch_cfg = SearchConfig(\n    top_k=5,\n    reranker=reranker_cfg,\n)\n\n# 初始化搜索引擎\nengine = SearchEngine(config=search_cfg, ...)\n\n# 执行搜索（自动触发重排序）\nresults = engine.search(\"项目架构设计原则\")\n```\n\n## 性能考量\n\n1. **候选集大小权衡**：`top_k_before_rerank` 过小可能导致遗漏相关文档，过大则增加交叉编码器的计算开销。默认值 `35` 在大多数场景下取得较好平衡。\n\n2. **模型选择**：交叉编码器模型直接影响重排序质量与推理速度。生产环境可根据硬件条件选择轻量级或高精度模型。\n\n3. **异步支持**：重排序阶段可与密集检索并行执行，通过合理的调度策略进一步降低端到端延迟。\n\n资料来源：[ARCHITECTURE.md:50-100]()\n\n## 配置示例\n\n```yaml\nsearch:\n  top_k: 5\n  reranker:\n    enabled: true\n    model: \"cross-encoder/ms-marco-MiniLM-L-6-v2\"\n    top_k_before_rerank: 35\n```\n\n该配置启用重排序功能，使用 `ms-marco-MiniLM-L-6-v2` 交叉编码器模型，在重排序前保留 35 个候选结果，最终返回 5 条最相关文档。\n\n---\n\n<a id='page-connectors'></a>\n\n## 数据连接器\n\n### 相关页面\n\n相关主题：[MCP 工具参考](#page-mcp-tools)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/connectors/registry.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/registry.py)\n- [src/memorymesh/connectors/confluence_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/confluence_connector.py)\n- [src/memorymesh/connectors/roam_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/roam_connector.py)\n- [src/memorymesh/connectors/logseq_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\n- [src/memorymesh/parsing/obsidian_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/obsidian_parser.py)\n- [src/memorymesh/parsing/notion_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/notion_parser.py)\n</details>\n\n# 数据连接器\n\n## 概述\n\n数据连接器（Connector）是 MemoryMesh 系统用于从外部数据源提取文档的核心模块。每个连接器实现特定平台的协议解析与数据拉取，将来自不同知识管理工具的原始数据转换为统一的 `ParsedDocument` 数据模型。\n\n连接器的设计遵循以下原则：\n\n- **统一接口** - 所有连接器实现 `fetch_documents()` 方法，返回 `Iterator[ParsedDocument]`\n- **配置驱动** - 每个连接器配套一个 Pydantic 配置类，通过 `config.yaml` 声明式配置\n- **懒加载注册** - 连接器通过 `CONNECTOR_REGISTRY` 字典按需注册，最小化导入开销\n- **解析器协同** - 部分连接器（如 Notion、Obsidian）依赖配套的解析器完成文件级别的数据转换\n\n资料来源：[src/memorymesh/connectors/registry.py:1-20]()\n\n## 架构设计\n\n### 组件关系图\n\n```mermaid\ngraph TD\n    A[config.yaml] --> B[ConnectorConfig]\n    B --> C[Connector]\n    C --> D{fetch_documents}\n    D --> E[Iterator[ParsedDocument]]\n    E --> F[FileIndexer]\n    F --> G[Chunker]\n    G --> H[EmbeddingProvider]\n    H --> I[VectorStore]\n    \n    J[CONNECTOR_REGISTRY] --> C\n    K[HTTP Auth] --> C\n```\n\n### 连接器类型矩阵\n\n| 类型标识 | 连接器类 | 配置类 | 数据源 | 认证方式 |\n|---------|---------|-------|--------|---------|\n| `confluence` | ConfluenceConnector | ConfluenceConfig | Confluence Cloud REST API | HTTP Basic |\n| `roam` | RoamConnector | RoamConfig | JSON 导出文件 | 无（本地文件） |\n| `logseq` | LogseqConnector | LogseqConfig | Graph 目录 | 无（本地文件） |\n| `notion` | NotionConnector | NotionConfig | Notion API | OAuth/API Token |\n| `jira` | JiraConnector | JiraConfig | Jira REST API | HTTP Basic |\n\n资料来源：[src/memorymesh/connectors/registry.py:25-50]()\n\n## 连接器注册机制\n\n### 注册表结构\n\n`CONNECTOR_REGISTRY` 是一个字典，将连接器类型字符串映射到 `(ConfigClass, ConnectorClass)` 元组：\n\n```python\nCONNECTOR_REGISTRY: dict[str, tuple[Any, Any]] = {}\n```\n\n注册在 `_register()` 函数中通过延迟导入完成，避免在模块初始化时导入所有依赖：\n\n```python\ndef _register() -> None:\n    \"\"\"Populate CONNECTOR_REGISTRY with all known connectors.\"\"\"\n    from memorymesh.connectors.airtable_connector import (\n        AirtableConfig,\n        AirtableConnector,\n    )\n    # ... 其他连接器导入\n```\n\n资料来源：[src/memorymesh/connectors/registry.py:15-40]()\n\n### 使用方式\n\nCLI 命令通过注册表动态实例化连接器：\n\n```python\ncfg_cls, conn_cls = CONNECTOR_REGISTRY[\"jira\"]\nconfig_obj = cfg_cls(**raw_config_dict)\nconnector = conn_cls(config_obj)\nfor doc in connector.fetch_documents():\n    indexer.index_parsed_document(doc)\n```\n\n## Confluence 连接器\n\n### 功能特性\n\n- **偏移分页** - 通过 `start` / `limit` 参数迭代获取所有页面\n- **空间过滤** - 可选限制特定空间密钥（space keys）\n- **HTML 清洗** - 将 `storage` 格式的页面体转换为纯文本\n- **日期过滤** - 跳过 `days_past` 时间窗口外的页面\n\n资料来源：[src/memorymesh/connectors/confluence_connector.py:1-30]()\n\n### 配置参数\n\n| 参数 | 类型 | 必填 | 说明 |\n|-----|------|-----|------|\n| `base_url` | str | 是 | Confluence Cloud 实例 URL |\n| `email` | SecretStr | 是 | Atlassian 账户邮箱 |\n| `api_token` | SecretStr | 是 | API Token（从 id.atlassian.com 生成） |\n| `space_keys` | list[str] | 否 | 限制的空间密钥列表 |\n| `days_past` | int | 否 | 保留最近 N 天内的页面（默认 90） |\n\n### 认证实现\n\nHTTP Basic 认证使用 `email:api_token` 组合的 base64 编码：\n\n```python\nfrom memorymesh.connectors._auth import basic_header\n```\n\n资料来源：[src/memorymesh/connectors/confluence_connector.py:40-45]()\n\n## Roam Research 连接器\n\n### 功能特性\n\n- **递归块扁平化** - 将嵌套块树展平为纯文本字符串\n- **Roam 语法清洗** - 移除 `{{[[...]]}}` 模板引用、`[[...]]` 页面引用、`#[[...]]` 和 `#tag` 标签语法\n- **日期过滤** - 跳过 `create-time` 或 `edit-time` 超出 `days_past` 窗口的页面\n- **空页面跳过** - 跳过无块内容的页面\n\n资料来源：[src/memorymesh/connectors/roam_connector.py:1-35]()\n\n### 导出格式\n\nRoam 导出为单个 JSON 文件，包含页面对象数组，每个对象具有：\n\n- `title` - 字符串\n- `children` - 嵌套块对象列表（块可递归包含 `children`）\n\n### 语法模式处理\n\n按顺序应用多个正则表达式清洗 Roam 特定语法：\n\n```python\n_ROAM_PATTERNS: list[re.Pattern[str]] = [\n    re.compile(r\"\\{\\{(\\[\\[.*?\\]\\])\"),  # 模板引用\n    re.compile(r\"\\[\\[.*?\\]\\]\"),        # 页面引用\n    re.compile(r\"#\\[\\[.*?\\]\\]\"),       # 标签页面引用\n    re.compile(r\"#\\w+\"),               # 标签\n]\n```\n\n资料来源：[src/memorymesh/connectors/roam_connector.py:55-60]()\n\n## Logseq 连接器\n\n### 功能特性\n\n- **多目录扫描** - 扫描 `pages/` 和 `journals/` 子目录\n- **语法转换** - 处理 Logseq 特定语法\n- **属性提取** - 从 `key:: value` 属性行提取元数据\n- **维基链接追踪** - 提取并去重的 `[[wikilinks]]` 存储在元数据中\n- **日记标记** - 期刊文件标记 `is_journal=True`\n\n资料来源：[src/memorymesh/connectors/logseq_connector.py:1-40]()\n\n### Logseq 语法处理对照表\n\n| 原始语法 | 处理方式 | 示例 |\n|---------|---------|------|\n| `((uuid))` | 转换为 `[block]` | `((abc123...))` → `[block]` |\n| `{{embed [[Page]]}}` | 转换为 `[embed: Page]` | `{{embed [[Note]]}}` → `[embed: Note]` |\n| `{{query ...}}` | 完全移除 | `{{query [[tag]]}}` → 移除 |\n| `key:: value` | 提取到元数据，从正文移除 | `tags:: #work` → metadata[\"tags\"] |\n| `[[wikilinks]]` | 保留原样 | `[[Page A]]` → `[[Page A]]` |\n| `- ` 块符号 | 保留为纯文本 | `- content` → `content` |\n\n资料来源：[src/memorymesh/connectors/logseq_connector.py:45-70]()\n\n### 文档处理流程\n\n```mermaid\ngraph LR\n    A[Markdown 文件] --> B[_process_file]\n    B --> C{文件存在?}\n    C -->|否| D[跳过]\n    C -->|是| E[读取文本]\n    E --> F[正则替换]\n    F --> G[属性提取]\n    G --> H[Wikilinks 提取]\n    H --> I[ParsedDocument]\n```\n\n资料来源：[src/memorymesh/connectors/logseq_connector.py:90-120]()\n\n## 配套解析器\n\n部分数据源需要专门的解析器处理文件格式，而非通过连接器直接拉取。\n\n### Notion HTML 解析器\n\nNotion 导出为单个 `.html` 文件，解析器从文件名提取 UUID、从 `<h1>` 或 `<title>` 提取标题：\n\n```python\n# UUID 模式：Page Title a1b2c3...html\n_UUID_FILENAME_RE = re.compile(\n    r\"([0-9a-f]{8}(?:[0-9a-f]{4}){3}[0-9a-f]{12})(?:\\s|\\.|$)\",\n    re.IGNORECASE,\n)\n```\n\n支持扩展名：`.html`, `.htm`\n\n提取的元数据字段：\n\n- `notion_id` - 页面 UUID\n- `database_name` - 父目录名\n- `db_properties` - 数据库属性列表\n\n资料来源：[src/memorymesh/parsing/notion_parser.py:25-45]()\n\n### Obsidian Markdown 解析器\n\nObsidian 解析器扩展基础 Markdown 解析：\n\n| 功能 | 说明 |\n|-----|------|\n| YAML Frontmatter | 提取 `tags`、`aliases`、`created`、`modified` 字段 |\n| Wikilink 提取 | 匹配 `[[link]]` 和 `[[link\\|alias]]` 模式 |\n| 内嵌过滤 | 排除 `![[img]]` 图片引用 |\n| 标签提取 | 从 frontmatter 和行内 `#tag` 提取标签 |\n\n支持的 frontmatter 字段映射：\n\n| Frontmatter 字段 | Metadata 键 |\n|----------------|------------|\n| `tags` | `tags` |\n| `aliases` | `aliases` |\n| `created` | `created` |\n| `modified` | `modified` |\n\n资料来源：[src/memorymesh/parsing/obsidian_parser.py:25-55]()\n\n### Frontmatter 解析正则\n\n```python\n_FRONTMATTER_RE = re.compile(\n    r\"^---\\r?\\n(.*?)\\r?\\n(?:---|\\.\\.\\.)(?:\\r?\\n|$)\",\n    re.DOTALL,\n)\n_WIKILINK_RE = re.compile(r\"(?<!!)\\[\\[([^\\[\\]|#]+?)(?:\\|[^\\[\\]]*?)?\\]\\]\")\n```\n\n## HTTP 辅助模块\n\n### 认证模块 (`_auth.py`)\n\n提供基础认证头生成：\n\n```python\nfrom memorymesh.connectors._auth import basic_header\n```\n\n支持标准 HTTP Basic 认证，用于 Confluence、Jira 等需要用户名/令牌的服务。\n\n### HTTP 模块 (`_http.py`)\n\n提供统一的 API 请求方法：\n\n```python\nfrom memorymesh.connectors._http import api_get\n```\n\n主要功能：\n\n- 自动添加认证头\n- 错误处理与日志记录\n- JSON 响应解析\n\n## 通用数据模型\n\n### ParsedDocument 结构\n\n所有连接器返回统一的 `ParsedDocument` 对象：\n\n| 字段 | 类型 | 说明 |\n|-----|------|------|\n| `path` | Path | 文件路径 |\n| `text` | str | 提取的纯文本内容 |\n| `file_type` | str | 规范化扩展名（如 `.md`、`.html`） |\n| `encoding` | str | 文本编码 |\n| `metadata` | dict | 源特定元数据 |\n\n### 配置基类模式\n\n每个连接器遵循统一配置模式：\n\n```python\nfrom pydantic import BaseModel\n\nclass ConnectorConfig(BaseModel):\n    export_path: Path | None = None      # 本地文件模式\n    days_past: int = 365                 # 日期过滤窗口\n```\n\n## 使用示例\n\n### 配置声明\n\n在 `config.yaml` 中声明数据源：\n\n```yaml\nsources:\n  - name: confluence-wiki\n    type: confluence\n    config:\n      base_url: \"https://myorg.atlassian.net\"\n      email: \"me@example.com\"\n      api_token: \"${CONFLUENCE_TOKEN}\"\n      space_keys: [\"ENG\", \"DOCS\"]\n      days_past: 90\n```\n\n### 代码使用\n\n```python\nfrom memorymesh.connectors.registry import CONNECTOR_REGISTRY\n\n# 通过注册表实例化\ncfg_cls, conn_cls = CONNECTOR_REGISTRY[\"confluence\"]\nconfig = cfg_cls(**source_config[\"config\"])\nconnector = conn_cls(config)\n\n# 迭代文档\nfor doc in connector.fetch_documents():\n    indexer.index_parsed_document(doc)\n```\n\n## 扩展新连接器\n\n添加新连接器的步骤：\n\n1. **创建连接器文件** - 在 `src/memorymesh/connectors/` 下创建 `xxx_connector.py`\n2. **定义配置类** - 创建 `XxxConfig(BaseModel)` 配置模型\n3. **实现连接器类** - 创建 `XxxConnector` 实现 `fetch_documents()` 方法\n4. **注册连接器** - 在 `registry.py` 的 `_register()` 函数中添加导入语句\n\n```mermaid\ngraph TD\n    A[创建 xxx_connector.py] --> B[定义 XxxConfig]\n    B --> C[实现 XxxConnector]\n    C --> D[实现 fetch_documents]\n    D --> E[更新 registry.py]\n```\n\n## 注意事项\n\n- **认证安全** - API Token 等敏感信息建议使用环境变量注入（`${VAR_NAME}` 语法）\n- **文件锁定** - 本地文件模式（如 Roam、Logseq）直接读取文件，注意并发写入\n- **分页处理** - API 类连接器需妥善处理分页，避免漏掉数据\n- **日期时区** - 日期比较使用 `datetime` 模块，配置 `UTC` 时区处理\n\n---\n\n<a id='page-mcp-tools'></a>\n\n## MCP 工具参考\n\n### 相关页面\n\n相关主题：[搜索引擎](#page-search-engine), [数据连接器](#page-connectors)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/server/tools/search_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/search_memory.py)\n- [src/memorymesh/server/tools/ask_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/ask_memory.py)\n- [src/memorymesh/server/tools/list_sources.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/list_sources.py)\n- [src/memorymesh/server/tools/get_document.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/get_document.py)\n- [src/memorymesh/server/tools/graph_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/graph_memory.py)\n- [src/memorymesh/server/tools/pin_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/pin_memory.py)\n- [src/memorymesh/server/tools/forget_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/forget_memory.py)\n- [src/memorymesh/server/app.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/app.py)\n- [src/memorymesh/core/models/search.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/search.py)\n</details>\n\n# MCP 工具参考\n\nMemoryMesh 通过 FastMCP 框架提供一组 MCP（Model Context Protocol）工具，使 LLM 客户端能够访问用户的本地知识库。所有工具均注册在 `FastMCP` 实例上，支持搜索、检索、索引管理、内存分层和知识图谱查询等核心功能。\n\n## 工具概览\n\nMemoryMesh MCP 工具分为以下几大类：\n\n| 类别 | 工具 | 功能描述 |\n|------|------|----------|\n| **搜索检索** | `search_memory` | 混合检索（向量 + BM25） |\n| | `ask_memory` | RAG 问答（基于 Ollama） |\n| | `search_by_date` | 按时间范围检索 |\n| | `related_documents` | 查找相关文档 |\n| **文档管理** | `list_sources` | 列出配置的索引源 |\n| | `get_document` | 获取完整文档内容 |\n| | `summarize_source` | 生成文档摘要 |\n| **索引控制** | `index_now` | 触发立即重建索引 |\n| | `sync_source` | 同步数据源 |\n| **内存分层** | `pin_memory` | 将分块固定到热层 |\n| | `unpin_memory` | 解除固定 |\n| | `forget_memory` | 抑制或冷置分块 |\n| **知识图谱** | `graph_memory` | 共现图查询 |\n| | `get_entity` | 获取实体信息 |\n| **时间线** | `query_timeline` | 查询活动历史 |\n\n资料来源：[src/memorymesh/server/app.py:36-52]()\n\n## 工具注册机制\n\n所有 MCP 工具通过统一的注册函数 `register(mcp, ctx)` 挂载到 FastMCP 实例：\n\n```python\ndef create_mcp(ctx: AppContext) -> FastMCP:\n    mcp: FastMCP = FastMCP(\n        name=\"memorymesh\",\n        instructions=(\n            \"MemoryMesh gives you read access to the user's personal knowledge \"\n            \"base — local files indexed from configured source directories.  \"\n            \"Use search_memory to find relevant passages, list_sources to \"\n            \"explore what has been indexed, get_document to read a full file, \"\n            \"index_now to trigger an immediate re-index, and ask_memory to \"\n            \"get an LLM-generated answer from your indexed content...\"\n        ),\n    )\n    \n    # 注册所有工具\n    search_memory.register(mcp, ctx)\n    list_sources.register(mcp, ctx)\n    get_document.register(mcp, ctx)\n    index_now.register(mcp, ctx)\n    ask_memory.register(mcp, ctx)\n    # ... 其他工具\n```\n\n工具注册采用依赖注入模式，`ctx`（AppContext）包含所有运行时依赖：搜索引擎、元数据存储、审计日志等。\n\n## 搜索检索类工具\n\n### search_memory\n\n混合检索工具，结合密集向量检索（embedding）和稀疏 BM25 检索。\n\n**函数签名：**\n\n```python\n@mcp.tool()\nasync def search_memory(\n    query: Annotated[str, \"要搜索的自然语言查询\"],\n    top_k: Annotated[int, \"返回的最大结果数\"] = 5,\n    mode: Annotated[\n        Literal[\"hybrid\", \"dense\", \"sparse\"],\n        \"hybrid: 密集+稀疏混合; dense: 仅向量; sparse: 仅BM25\"\n    ] = \"hybrid\",\n    source_filter: Annotated[\n        list[str] | None,\n        \"限制搜索的源名称列表\"\n    ] = None,\n    modality: Annotated[\n        Literal[\"all\", \"text\", \"image\"],\n        \"搜索的模态类型\"\n    ] = \"all\",\n) -> SearchResponse\n```\n\n**返回类型（SearchResponse）：**\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `hits` | `list[SearchHit]` | 排序后的搜索结果列表 |\n| `mode` | `\"hybrid\" \\| \"dense\" \\| \"sparse\"` | 使用的检索模式 |\n| `duration_ms` | `float` | 查询总延迟（毫秒） |\n\n资料来源：[src/memorymesh/core/models/search.py:1-30]()\n\n### ask_memory\n\nRAG 问答工具，基于 Ollama 本地 LLM 生成答案。\n\n**核心机制：**\n\n```\n用户问题 → search_memory → 构建上下文 → Ollama generate → 答案 + 引用源\n```\n\n**函数签名：**\n\n```python\n@mcp.tool()\nasync def ask_memory(\n    question: str,\n    top_k: int = 5,\n    model: str | None = None,\n) -> AskMemoryResponse\n```\n\n**上下文构建参数：**\n\n- `_MAX_CONTEXT_CHARS_PER_HIT = 800`：每个来源片段最多包含 800 字符\n\n**系统提示词模板：**\n\n```python\n_RAG_SYSTEM_PREAMBLE = (\n    \"You are a helpful assistant answering questions about the user's personal \"\n    \"knowledge base. Use only the provided source passages to answer. \"\n    \"If the answer is not in the sources, say so clearly. \"\n    \"Cite the source file paths when relevant.\"\n)\n```\n\n**返回类型（AskMemoryResponse）：**\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `answer` | `str \\| None` | LLM 生成的答案 |\n| `sources` | `list[SearchHit]` | 检索到的来源片段 |\n| `model` | `str` | 使用的 Ollama 模型 |\n| `ollama_available` | `bool` | Ollama 是否可用 |\n| `hint` | `str \\| None` | 仅在 Ollama 不可用时返回安装提示 |\n\n> **容错设计**：当 Ollama 不可用时，`ask_memory` 仍返回检索结果和安装提示，绝不静默失败。\n\n资料来源：[src/memorymesh/server/tools/ask_memory.py:1-50]()\n\n### search_by_date\n\n按时间范围检索文档变更历史。\n\n**典型用途：** 查找特定时间段内修改过的文件内容。\n\n### related_documents\n\n基于共现关系查找相关文档，输入一个 chunk_id，返回与其在相同上下文中出现的其他文档。\n\n## 文档管理类工具\n\n### list_sources\n\n列出所有配置的索引源及其统计信息。\n\n**返回类型（SourcesReport）：**\n\n```python\nclass SourcesReport(BaseModel):\n    sources: list[SourceStats]\n\nclass SourceStats(BaseModel):\n    name: str                    # 源名称\n    path: str                    # 源路径\n    recursive: bool              # 是否递归\n    n_files_indexed: int         # 已索引文件数\n    n_files_pending: int         # 待处理文件数\n    n_files_errored: int         # 错误文件数\n    last_scan_at: float | None   # 上次扫描时间\n    total_chunks: int            # 总分块数\n    disk_size_bytes: int         # 磁盘占用\n```\n\n### get_document\n\n获取完整文档内容。\n\n**函数签名：**\n\n```python\n@mcp.tool()\nasync def get_document(\n    path: Annotated[str, \"文档的绝对路径\"],\n    max_bytes: Annotated[int, \"最大读取字节数\"] = 1_000_000,\n) -> DocumentResponse\n```\n\n**返回类型（DocumentResponse）：**\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `path` | `str` | 文档绝对路径 |\n| `content` | `str` | 文件内容（可能截断） |\n| `file_type` | `str` | 标准化文件扩展名 |\n| `size_bytes` | `int` | 原始文件大小 |\n| `mtime` | `float` | 修改时间戳 |\n| `truncated` | `bool` | 是否被截断 |\n\n**异常处理：**\n\n- `DocumentNotFoundError`：路径不在任何配置的源中\n- `DocumentTooLargeError`：文件超过 `max_bytes`，返回开头 + 摘要\n\n资料来源：[src/memorymesh/core/models/search.py:45-70]()\n\n### summarize_source\n\n对指定源目录生成摘要信息，支持深度分析和要点提取。\n\n## 索引控制类工具\n\n### index_now\n\n强制重新索引指定路径。\n\n```python\n@mcp.tool()\nasync def index_now(\n    path: str,\n    recursive: bool = True,\n) -> IndexResponse\n```\n\n**约束条件：**\n\n- 路径必须在某个配置的源目录内\n- 返回处理统计：文件数、分块数、耗时\n\n### sync_source\n\n同步数据源，扫描新增、修改和删除的文件，更新索引。\n\n## 内存分层类工具\n\nMemoryMesh 支持内存分层（Memory Tiers），将分块分为 hot、warm、cold 层级，实现访问频率感知的存储优化。\n\n### 内存层级说明\n\n| 层级 | 说明 | 自动行为 |\n|------|------|----------|\n| **hot** | 热点数据，高频访问 | 手动固定或自动提升 |\n| **warm** | 温数据 | 定期维护时根据访问频率调整 |\n| **cold** | 冷数据 | 逐步降级，评分衰减 |\n\n### pin_memory / unpin_memory\n\n将分块固定到热层或解除固定。\n\n```python\n@mcp.tool()\ndef pin_memory(\n    chunk_id: Annotated[str, \"分块标识符，格式为 '<path>:<chunk_index>'\"],\n) -> dict:\n    \"\"\"固定分块到热层\"\"\"\n    return {\"chunk_id\": chunk_id, \"tier\": \"hot\", \"pinned\": True}\n\n@mcp.tool()\ndef unpin_memory(\n    chunk_id: Annotated[str, \"分块标识符，格式为 '<path>:<chunk_index>'\"],\n) -> dict:\n    \"\"\"解除固定，允许正常层级调整\"\"\"\n    return {\"chunk_id\": chunk_id, \"pinned\": False}\n```\n\n> 解除固定后，分块在下次维护运行前保留在热层，之后根据访问历史进行升降级。\n\n资料来源：[src/memorymesh/server/tools/pin_memory.py:1-60]()\n\n### forget_memory\n\n抑制或冷置分块，实现内容的渐进式遗忘。\n\n```python\n@mcp.tool()\ndef forget_memory(\n    chunk_id: Annotated[\n        str,\n        \"分块标识符，格式为 '<absolute_path>:<chunk_index>'\",\n    ],\n    mode: Annotated[\n        Literal[\"suppress\", \"cold\"],\n        \"'suppress': 立即隐藏; 'cold': 降级到冷层，评分逐渐衰减\"\n    ] = \"suppress\",\n) -> dict\n```\n\n**模式对比：**\n\n| 模式 | 行为 | 可逆性 |\n|------|------|--------|\n| `suppress` | 加入抑制列表，立即从搜索结果中隐藏 | 不可逆（需直接数据库访问） |\n| `cold` | 降级到冷层，评分逐渐衰减 | 可通过 `pin_memory` 恢复 |\n\n资料来源：[src/memorymesh/server/tools/forget_memory.py:1-50]()\n\n## 知识图谱类工具\n\n### graph_memory\n\n共现图查询工具，基于实体共现关系构建知识图谱。\n\n**典型用途：**\n\n- 发现概念间的关联\n- 探索特定实体类型的分布\n- 设定最小提及阈值过滤噪声\n\n**服务端缓存：** 图数据在服务器端缓存 60 秒，减少重复计算。\n\n### get_entity\n\n查询特定实体的详细信息，包括属性、关系和上下文。\n\n## 时间线类工具\n\n### query_timeline\n\n查询活动历史记录，包括索引操作、查询历史和变更事件。\n\n**审计日志字段：**\n\n| 字段 | 说明 |\n|------|------|\n| `ts` | 时间戳 |\n| `tool` | 调用的工具名称 |\n| `query_hash` | 查询的 SHA256 哈希（截断至 16 字符） |\n| `n_results` | 返回结果数 |\n| `latency_ms` | 延迟（毫秒） |\n| `client_id_if_known` | 客户端标识（已知时） |\n\n> **隐私保护**：审计日志不包含文档内容、chunk 内容或明文查询。\n\n## 工具调用流程\n\n```mermaid\nsequenceDiagram\n    participant Client as LLM 客户端\n    participant MCP as FastMCP 服务器\n    participant Engine as 搜索引擎\n    participant DB as 元数据存储\n    participant Ollama as Ollama LLM\n\n    Client->>MCP: search_memory(query, top_k)\n    MCP->>Engine: 混合检索\n    Engine->>DB: 查询向量 + BM25\n    DB-->>Engine: SearchHit 列表\n    Engine-->>MCP: SearchResponse\n    MCP-->>Client: hits + duration_ms\n\n    Client->>MCP: ask_memory(question)\n    MCP->>MCP: search_memory(question, top_k)\n    MCP->>Ollama: generate(RAG_prompt)\n    Ollama-->>MCP: answer\n    MCP-->>Client: AskMemoryResponse\n\n    Note over Client,DB: 写操作（index_now、pin_memory 等）\n    Client->>MCP: index_now(path)\n    MCP->>DB: 验证路径有效性\n    MCP->>Engine: 重新索引\n    Engine->>DB: 更新元数据\n    DB-->>MCP: IndexResponse\n    MCP-->>Client: 处理统计\n```\n\n## 访问控制与审计\n\n### 认证守卫\n\n工具注册时通过 `check_access(ctx, operation)` 检查访问权限：\n\n```python\nfrom memorymesh.server.auth_guard import check_access\n\nif (err := check_access(ctx, \"index\")) is not None:\n    return err\n```\n\n### 审计日志\n\n每次工具调用都会记录到 `~/.memorymesh/audit.jsonl`：\n\n```json\n{\"ts\": 1703001234.567, \"tool\": \"search_memory\", \"query_hash\": \"a1b2c3d4e5f6g7h8\", \"n_results\": 5, \"latency_ms\": 42.3}\n```\n\n## 配置与扩展\n\n### 配置来源优先级\n\n```python\n_DEFAULT_SEARCH_PATHS = [\n    Path.cwd() / \"config.yaml\",           # 1. 当前工作目录\n    Path.home() / \".memorymesh\" / \"config.yaml\",  # 2. 用户配置目录\n]\n```\n\n### 必需配置示例\n\n```yaml\nsources:\n  - name: documents\n    path: ~/Documents\n    recursive: true\n    extensions: [.txt, .md, .pdf]\n\nembeddings:\n  model: \"sentence-transformers/all-MiniLM-L6-v2\"\n\nollama:\n  enabled: true\n  model: \"llama2\"\n```\n\n## 错误处理规范\n\n| 错误类型 | 返回方式 | 说明 |\n|----------|----------|------|\n| 配置错误 | 抛出 `ConfigError` | YAML 解析或验证失败 |\n| 文档未找到 | 返回 `DocumentNotFoundError` | 路径不在任何源中 |\n| 文档过大 | 返回部分内容 + `DocumentTooLargeError` | 包含开头和摘要 |\n| Ollama 不可用 | 返回 `hint` | `ask_memory` 的容错机制 |\n| 访问被拒 | 返回错误字典 | `check_access` 拦截 |\n\n## 工具元数据速查\n\n| 工具名称 | 返回类型 | 异步 | LLM 依赖 |\n|----------|----------|------|----------|\n| `search_memory` | `SearchResponse` | ✅ | ❌ |\n| `ask_memory` | `AskMemoryResponse` | ✅ | Ollama |\n| `list_sources` | `SourcesReport` | ❌ | ❌ |\n| `get_document` | `DocumentResponse` | ✅ | ❌ |\n| `index_now` | `IndexResponse` | ✅ | ❌ |\n| `pin_memory` | `dict` | ❌ | ❌ |\n| `unpin_memory` | `dict` | ❌ | ❌ |\n| `forget_memory` | `dict` | ❌ | ❌ |\n| `graph_memory` | `dict` | ❌ | ❌ |\n| `get_entity` | `dict` | ❌ | ❌ |\n| `query_timeline` | `dict` | ❌ | ❌ |\n| `search_by_date` | `SearchResponse` | ❌ | ❌ |\n| `related_documents` | `list[SearchHit]` | ❌ | ❌ |\n| `summarize_source` | `dict` | ❌ | ❌ |\n| `sync_source` | `dict` | ❌ | ❌ |\n\n资料来源：[src/memorymesh/server/app.py:36-52]()\n\n---\n\n---\n\n## Doramagic 踩坑日志\n\n项目：kilhubprojects/memory-mesh\n\n摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。\n\n## 1. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | README/documentation is current enough for a first validation pass.\n\n## 2. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | last_activity_observed missing\n\n## 3. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | no_demo; severity=medium\n\n## 4. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | no_demo; severity=medium\n\n## 5. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | issue_or_pr_quality=unknown\n\n## 6. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | release_recency=unknown\n\n<!-- canonical_name: kilhubprojects/memory-mesh; human_manual_source: deepwiki_human_wiki -->\n",
      "markdown_key": "memory-mesh",
      "pages": "draft",
      "source_refs": [
        {
          "evidence_id": "github_repo:1238654023",
          "kind": "repo",
          "supports_claim_ids": [
            "claim_identity",
            "claim_distribution",
            "claim_capability"
          ],
          "url": "https://github.com/kilhubprojects/memory-mesh"
        },
        {
          "evidence_id": "art_df5c7ee303204fdc8a46d706269ed6e3",
          "kind": "docs",
          "supports_claim_ids": [
            "claim_identity",
            "claim_distribution",
            "claim_capability"
          ],
          "url": "https://github.com/kilhubprojects/memory-mesh#readme"
        }
      ],
      "summary": "DeepWiki/Human Wiki 完整输出，末尾追加 Discovery Agent 踩坑日志。",
      "title": "memory-mesh 说明书",
      "toc": [
        "https://github.com/kilhubprojects/memory-mesh 项目说明书",
        "目录",
        "MemoryMesh 简介",
        "系统架构",
        "核心模块",
        "数据模型",
        "服务端组件",
        "搜索架构",
        "Doramagic 踩坑日志"
      ]
    }
  },
  "quality_gate": {
    "blocking_gaps": [],
    "category_confidence": "medium",
    "compile_status": "ready_for_review",
    "five_assets_present": true,
    "install_sandbox_verified": true,
    "missing_evidence": [],
    "next_action": "publish to Doramagic.ai project surfaces",
    "prompt_preview_boundary_ok": true,
    "publish_status": "publishable",
    "quick_start_verified": true,
    "repo_clone_verified": true,
    "repo_commit": "bbf24d6918789e8e9eac56bdc2e11c606699ba4b",
    "repo_inspection_error": null,
    "repo_inspection_files": [
      "pyproject.toml",
      "Dockerfile",
      "README.md",
      "docker-compose.yml",
      "uv.lock",
      "src/memorymesh/cli.py",
      "src/memorymesh/__init__.py",
      "src/memorymesh/config.py",
      "src/memorymesh/__main__.py",
      "src/memorymesh/embeddings/registry.py",
      "src/memorymesh/embeddings/sentence_transformers_provider.py",
      "src/memorymesh/embeddings/__init__.py",
      "src/memorymesh/embeddings/cache.py",
      "src/memorymesh/embeddings/base.py",
      "src/memorymesh/llm/ollama_client.py",
      "src/memorymesh/llm/__init__.py",
      "src/memorymesh/connectors/mastodon_connector.py",
      "src/memorymesh/connectors/gitlab_connector.py",
      "src/memorymesh/connectors/_auth.py",
      "src/memorymesh/connectors/bank_csv_connector.py",
      "src/memorymesh/connectors/caldav_connector.py",
      "src/memorymesh/connectors/reddit_connector.py",
      "src/memorymesh/connectors/pocket_connector.py",
      "src/memorymesh/connectors/telegram_connector.py",
      "src/memorymesh/connectors/browser_history_connector.py",
      "src/memorymesh/connectors/whatsapp_connector.py",
      "src/memorymesh/connectors/twitter_connector.py",
      "src/memorymesh/connectors/kindle_connector.py",
      "src/memorymesh/connectors/github_connector.py",
      "src/memorymesh/connectors/jira_connector.py",
      "src/memorymesh/connectors/_html.py",
      "src/memorymesh/connectors/hackernews_connector.py",
      "src/memorymesh/connectors/pinterest_connector.py",
      "src/memorymesh/connectors/roam_connector.py",
      "src/memorymesh/connectors/rss_connector.py",
      "src/memorymesh/connectors/linear_connector.py",
      "src/memorymesh/connectors/hypothesis_connector.py",
      "src/memorymesh/connectors/imap_connector.py",
      "src/memorymesh/connectors/slack_connector.py",
      "src/memorymesh/connectors/registry.py"
    ],
    "repo_inspection_verified": true,
    "review_reasons": [
      "community_discussion_evidence_below_public_threshold"
    ],
    "tag_count_ok": true,
    "unsupported_claims": []
  },
  "schema_version": "0.1",
  "user_assets": {
    "ai_context_pack": {
      "asset_id": "ai_context_pack",
      "filename": "AI_CONTEXT_PACK.md",
      "markdown": "# memorymesh - Doramagic AI Context Pack\n\n> 定位：安装前体验与判断资产。它帮助宿主 AI 有一个好的开始，但不代表已经安装、执行或验证目标项目。\n\n## 充分原则\n\n- **充分原则，不是压缩原则**：AI Context Pack 应该充分到让宿主 AI 在开工前理解项目价值、能力边界、使用入口、风险和证据来源；它可以分层组织，但不以最短摘要为目标。\n- **压缩策略**：只压缩噪声和重复内容，不压缩会影响判断和开工质量的上下文。\n\n## 给宿主 AI 的使用方式\n\n你正在读取 Doramagic 为 memorymesh 编译的 AI Context Pack。请把它当作开工前上下文：帮助用户理解适合谁、能做什么、如何开始、哪些必须安装后验证、风险在哪里。不要声称你已经安装、运行或执行了目标项目。\n\n## Claim 消费规则\n\n- **事实来源**：Repo Evidence + Claim/Evidence Graph；Human Wiki 只提供显著性、术语和叙事结构。\n- **事实最低状态**：`supported`\n- `supported`：可以作为项目事实使用，但回答中必须引用 claim_id 和证据路径。\n- `weak`：只能作为低置信度线索，必须要求用户继续核实。\n- `inferred`：只能用于风险提示或待确认问题，不能包装成项目事实。\n- `unverified`：不得作为事实使用，应明确说证据不足。\n- `contradicted`：必须展示冲突来源，不得替用户强行选择一个版本。\n\n## 它最适合谁\n\n- **AI 研究者或研究型 Agent 构建者**：README 明确围绕研究、实验或论文工作流展开。 证据：`README.md` Claim：`clm_0002` supported 0.86\n- **正在使用 Claude/Codex/Cursor/Gemini 等宿主 AI 的开发者**：README 或插件配置提到多个宿主 AI。 证据：`README.md` Claim：`clm_0003` supported 0.86\n\n## 它能做什么\n\n- **命令行启动或安装流程**（需要安装后验证）：项目文档中存在可执行命令，真实使用需要在本地或宿主环境中运行这些命令。 证据：`README.md` Claim：`clm_0001` supported 0.86\n\n## 怎么开始\n\n- `pip install memorymesh-mcp` 证据：`README.md` Claim：`clm_0004` supported 0.86\n\n## 继续前判断卡\n\n- **当前建议**：先做权限沙盒试用\n- **为什么**：项目存在安装命令、宿主配置或本地写入线索，不建议直接进入主力环境，应先在隔离环境试装。\n\n### 30 秒判断\n\n- **现在怎么做**：先做权限沙盒试用\n- **最小安全下一步**：先跑 Prompt Preview；若仍要安装，只在隔离环境试装\n- **先别相信**：工具权限边界不能在安装前相信。\n- **继续会触碰**：命令执行、本地环境或项目文件、宿主 AI 上下文\n\n### 现在可以相信\n\n- **适合人群线索：AI 研究者或研究型 Agent 构建者**（supported）：有 supported claim 或项目证据支撑，但仍不等于真实安装效果。 证据：`README.md` Claim：`clm_0002` supported 0.86\n- **适合人群线索：正在使用 Claude/Codex/Cursor/Gemini 等宿主 AI 的开发者**（supported）：有 supported claim 或项目证据支撑，但仍不等于真实安装效果。 证据：`README.md` Claim：`clm_0003` supported 0.86\n- **能力存在：命令行启动或安装流程**（supported）：可以相信项目包含这类能力线索；是否适合你的具体任务仍要试用或安装后验证。 证据：`README.md` Claim：`clm_0001` supported 0.86\n- **存在 Quick Start / 安装命令线索**（supported）：可以相信项目文档出现过启动或安装入口；不要因此直接在主力环境运行。 证据：`README.md` Claim：`clm_0004` supported 0.86\n\n### 现在还不能相信\n\n- **工具权限边界不能在安装前相信。**（unverified）：MCP/tool 类项目通常会触碰文件、网络、浏览器或外部 API，必须真实检查权限和日志。\n- **真实输出质量不能在安装前相信。**（unverified）：Prompt Preview 只能展示引导方式，不能证明真实项目中的结果质量。\n- **宿主 AI 版本兼容性不能在安装前相信。**（unverified）：Claude、Cursor、Codex、Gemini 等宿主加载规则和版本差异必须在真实环境验证。\n- **不会污染现有宿主 AI 行为，不能直接相信。**（inferred）：Skill、plugin、AGENTS/CLAUDE/GEMINI 指令可能改变宿主 AI 的默认行为。\n- **可安全回滚不能默认相信。**（unverified）：除非项目明确提供卸载和恢复说明，否则必须先在隔离环境验证。\n- **真实安装后是否与用户当前宿主 AI 版本兼容？**（unverified）：兼容性只能通过实际宿主环境验证。\n- **项目输出质量是否满足用户具体任务？**（unverified）：安装前预览只能展示流程和边界，不能替代真实评测。\n- **安装命令是否需要网络、权限或全局写入？**（unverified）：这影响企业环境和个人环境的安装风险。 证据：`README.md`\n\n### 继续会触碰什么\n\n- **命令执行**：包管理器、网络下载、本地插件目录、项目配置或用户主目录。 原因：运行第一条命令就可能产生环境改动；必须先判断是否值得跑。 证据：`README.md`\n- **本地环境或项目文件**：安装结果、插件缓存、项目配置或本地依赖目录。 原因：安装前无法证明写入范围和回滚方式，需要隔离验证。 证据：`README.md`\n- **宿主 AI 上下文**：AI Context Pack、Prompt Preview、Skill 路由、风险规则和项目事实。 原因：导入上下文会影响宿主 AI 后续判断，必须避免把未验证项包装成事实。\n\n### 最小安全下一步\n\n- **先跑 Prompt Preview**：用安装前交互式试用判断工作方式是否匹配，不需要授权或改环境。（适用：任何项目都适用，尤其是输出质量未知时。）\n- **只在隔离目录或测试账号试装**：避免安装命令污染主力宿主 AI、真实项目或用户主目录。（适用：存在命令执行、插件配置或本地写入线索时。）\n- **安装后只验证一个最小任务**：先验证加载、兼容、输出质量和回滚，再决定是否深用。（适用：准备从试用进入真实工作流时。）\n\n### 退出方式\n\n- **保留安装前状态**：记录原始宿主配置和项目状态，后续才能判断是否可恢复。\n- **记录安装命令和写入路径**：没有明确卸载说明时，至少要知道哪些目录或配置需要手动清理。\n- **如果没有回滚路径，不进入主力环境**：不可回滚是继续前阻断项，不应靠信任或运气继续。\n\n## 哪些只能预览\n\n- 解释项目适合谁和能做什么\n- 基于项目文档演示典型对话流程\n- 帮助用户判断是否值得安装或继续研究\n\n## 哪些必须安装后验证\n\n- 真实安装 Skill、插件或 CLI\n- 执行脚本、修改本地文件或访问外部服务\n- 验证真实输出质量、性能和兼容性\n\n## 边界与风险判断卡\n\n- **把安装前预览误认为真实运行**：用户可能高估项目已经完成的配置、权限和兼容性验证。 处理方式：明确区分 prompt_preview_can_do 与 runtime_required。 Claim：`clm_0005` inferred 0.45\n- **命令执行会修改本地环境**：安装命令可能写入用户主目录、宿主插件目录或项目配置。 处理方式：先在隔离环境或测试账号中运行。 证据：`README.md` Claim：`clm_0006` supported 0.86\n- **待确认**：真实安装后是否与用户当前宿主 AI 版本兼容？。原因：兼容性只能通过实际宿主环境验证。\n- **待确认**：项目输出质量是否满足用户具体任务？。原因：安装前预览只能展示流程和边界，不能替代真实评测。\n- **待确认**：安装命令是否需要网络、权限或全局写入？。原因：这影响企业环境和个人环境的安装风险。\n\n## 开工前工作上下文\n\n### 加载顺序\n\n- 先读取 how_to_use.host_ai_instruction，建立安装前判断资产的边界。\n- 读取 claim_graph_summary，确认事实来自 Claim/Evidence Graph，而不是 Human Wiki 叙事。\n- 再读取 intended_users、capabilities 和 quick_start_candidates，判断用户是否匹配。\n- 需要执行具体任务时，优先查 role_skill_index，再查 evidence_index。\n- 遇到真实安装、文件修改、网络访问、性能或兼容性问题时，转入 risk_card 和 boundaries.runtime_required。\n\n### 任务路由\n\n- **命令行启动或安装流程**：先说明这是安装后验证能力，再给出安装前检查清单。 边界：必须真实安装或运行后验证。 证据：`README.md` Claim：`clm_0001` supported 0.86\n\n### 上下文规模\n\n- 文件总数：232\n- 重要文件覆盖：28/232\n- 证据索引条目：28\n- 角色 / Skill 条目：8\n\n### 证据不足时的处理\n\n- **missing_evidence**：说明证据不足，要求用户提供目标文件、README 段落或安装后验证记录；不要补全事实。\n- **out_of_scope_request**：说明该任务超出当前 AI Context Pack 证据范围，并建议用户先查看 Human Manual 或真实安装后验证。\n- **runtime_request**：给出安装前检查清单和命令来源，但不要替用户执行命令或声称已执行。\n- **source_conflict**：同时展示冲突来源，标记为待核实，不要强行选择一个版本。\n\n## Prompt Recipes\n\n### 适配判断\n\n- 目标：判断这个项目是否适合用户当前任务。\n- 预期输出：适配结论、关键理由、证据引用、安装前可预览内容、必须安装后验证内容、下一步建议。\n\n```text\n请基于 memorymesh 的 AI Context Pack，先问我 3 个必要问题，然后判断它是否适合我的任务。回答必须包含：适合谁、能做什么、不能做什么、是否值得安装、证据来自哪里。所有项目事实必须引用 evidence_refs、source_paths 或 claim_id。\n```\n\n### 安装前体验\n\n- 目标：让用户在安装前感受核心工作流，同时避免把预览包装成真实能力或营销承诺。\n- 预期输出：一段带边界标签的体验剧本、安装后验证清单和谨慎建议；不含真实运行承诺或强营销表述。\n\n```text\n请把 memorymesh 当作安装前体验资产，而不是已安装工具或真实运行环境。\n\n请严格输出四段：\n1. 先问我 3 个必要问题。\n2. 给出一段“体验剧本”：用 [安装前可预览]、[必须安装后验证]、[证据不足] 三种标签展示它可能如何引导工作流。\n3. 给出安装后验证清单：列出哪些能力只有真实安装、真实宿主加载、真实项目运行后才能确认。\n4. 给出谨慎建议：只能说“值得继续研究/试装”“先补充信息后再判断”或“不建议继续”，不得替项目背书。\n\n硬性边界：\n- 不要声称已经安装、运行、执行测试、修改文件或产生真实结果。\n- 不要写“自动适配”“确保通过”“完美适配”“强烈建议安装”等承诺性表达。\n- 如果描述安装后的工作方式，必须使用“如果安装成功且宿主正确加载 Skill，它可能会……”这种条件句。\n- 体验剧本只能写成“示例台词/假设流程”：使用“可能会询问/可能会建议/可能会展示”，不要写“已写入、已生成、已通过、正在运行、正在生成”。\n- Prompt Preview 不负责给安装命令；如用户准备试装，只能提示先阅读 Quick Start 和 Risk Card，并在隔离环境验证。\n- 所有项目事实必须来自 supported claim、evidence_refs 或 source_paths；inferred/unverified 只能作风险或待确认项。\n\n```\n\n### 角色 / Skill 选择\n\n- 目标：从项目里的角色或 Skill 中挑选最匹配的资产。\n- 预期输出：候选角色或 Skill 列表，每项包含适用场景、证据路径、风险边界和是否需要安装后验证。\n\n```text\n请读取 role_skill_index，根据我的目标任务推荐 3-5 个最相关的角色或 Skill。每个推荐都要说明适用场景、可能输出、风险边界和 evidence_refs。\n```\n\n### 风险预检\n\n- 目标：安装或引入前识别环境、权限、规则冲突和质量风险。\n- 预期输出：环境、权限、依赖、许可、宿主冲突、质量风险和未知项的检查清单。\n\n```text\n请基于 risk_card、boundaries 和 quick_start_candidates，给我一份安装前风险预检清单。不要替我执行命令，只说明我应该检查什么、为什么检查、失败会有什么影响。\n```\n\n### 宿主 AI 开工指令\n\n- 目标：把项目上下文转成一次对话开始前的宿主 AI 指令。\n- 预期输出：一段边界明确、证据引用明确、适合复制给宿主 AI 的开工前指令。\n\n```text\n请基于 memorymesh 的 AI Context Pack，生成一段我可以粘贴给宿主 AI 的开工前指令。这段指令必须遵守 not_runtime=true，不能声称项目已经安装、运行或产生真实结果。\n```\n\n\n## 角色 / Skill 索引\n\n- 共索引 8 个角色 / Skill / 项目文档条目。\n\n- **MemoryMesh**（project_doc）：! PyPI https://img.shields.io/pypi/v/memorymesh-mcp https://pypi.org/project/memorymesh-mcp/ ! License https://img.shields.io/badge/license-MIT-blue ./LICENSE ! Python https://img.shields.io/badge/python-3.11+-blue https://www.python.org/ ! CI https://img.shields.io/github/actions/workflow/status/kilhubprojects/memory-mesh/ci.yml?label=CI https://github.com/kilhubprojects/memory-mesh/actions ! Tests https://img.shie… 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`README.md`\n- **Contributing to MemoryMesh**（project_doc）：Thank you for your interest in contributing. This document covers everything you need to go from a fresh clone to an approved pull request. 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`CONTRIBUTING.md`\n- **Summary**（project_doc）：- Bug fix - New feature - Refactor / cleanup - Documentation - CI / tooling 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`.github/pull_request_template.md`\n- **ARCHITECTURE.md — MemoryMesh**（project_doc）：Arquitetura técnica do MVP. Toda decisão aqui já foi travada ver MVP SCOPE.md para o \"porquê\" . Tudo é modular e abstraído porque a versão pós-MVP vai trocar componentes embeddings melhores, novos parsers, novos transports . 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`ARCHITECTURE.md`\n- **Changelog**（project_doc）：All notable changes to this project will be documented in this file. 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`CHANGELOG.md`\n- **ROADMAP.md — MemoryMesh**（project_doc）：Visão de longo prazo, do MVP ao \"where this all leads\". Última atualização: 2026-05-13. Baseado em análise competitiva de 14 projetos similares + auto-crítica do código + papers recentes 2024-2025 sobre retrieval e memória de agentes. 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`ROADMAP.md`\n- **Bug report**（project_doc）：A clear description of what is wrong. 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`.github/ISSUE_TEMPLATE/bug_report.md`\n- **Feature request**（project_doc）：What problem does this solve? Who benefits? 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`.github/ISSUE_TEMPLATE/feature_request.md`\n\n## 证据索引\n\n- 共索引 28 条证据。\n\n- **MemoryMesh**（documentation）：! PyPI https://img.shields.io/pypi/v/memorymesh-mcp https://pypi.org/project/memorymesh-mcp/ ! License https://img.shields.io/badge/license-MIT-blue ./LICENSE ! Python https://img.shields.io/badge/python-3.11+-blue https://www.python.org/ ! CI https://img.shields.io/github/actions/workflow/status/kilhubprojects/memory-mesh/ci.yml?label=CI https://github.com/kilhubprojects/memory-mesh/actions ! Tests https://img.shields.io/badge/tests-CI%20validated-brightgreen ! v0.8.0 https://img.shields.io/badge/version-v0.8.0-orange https://github.com/kilhubprojects/memory-mesh/releases/tag/v0.8.0 证据：`README.md`\n- **Contributing to MemoryMesh**（documentation）：Thank you for your interest in contributing. This document covers everything you need to go from a fresh clone to an approved pull request. 证据：`CONTRIBUTING.md`\n- **Package**（package_manifest）：{ \"name\": \"memorymesh\", \"displayName\": \"MemoryMesh\", \"description\": \"Semantic search over your personal knowledge base via MemoryMesh.\", \"version\": \"0.8.0\", \"publisher\": \"memorymesh\", \"license\": \"MIT\", \"repository\": { \"type\": \"git\", \"url\": \"https://github.com/kilhubprojects/memory-mesh\" }, \"engines\": { \"vscode\": \"^1.85.0\" }, \"categories\": \"Other\", \"AI\" , \"activationEvents\": \"onStartupFinished\" , \"main\": \"./out/extension.js\", \"contributes\": { \"commands\": { \"command\": \"memorymesh.search\", \"title\": \"MemoryMesh: Search Knowledge Base\", \"icon\": \"$ search \" }, { \"command\": \"memorymesh.indexNow\", \"title\": \"MemoryMesh: Index Now\" }, { \"command\": \"memorymesh.showStatus\", \"title\": \"MemoryMesh: Show S… 证据：`extensions/vscode/package.json`\n- **License**（source_file）：Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files the \"Software\" , to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 证据：`LICENSE`\n- **Summary**（documentation）：- Bug fix - New feature - Refactor / cleanup - Documentation - CI / tooling 证据：`.github/pull_request_template.md`\n- **ARCHITECTURE.md — MemoryMesh**（documentation）：Arquitetura técnica do MVP. Toda decisão aqui já foi travada ver MVP SCOPE.md para o \"porquê\" . Tudo é modular e abstraído porque a versão pós-MVP vai trocar componentes embeddings melhores, novos parsers, novos transports . 证据：`ARCHITECTURE.md`\n- **Changelog**（documentation）：All notable changes to this project will be documented in this file. 证据：`CHANGELOG.md`\n- **ROADMAP.md — MemoryMesh**（documentation）：Visão de longo prazo, do MVP ao \"where this all leads\". Última atualização: 2026-05-13. Baseado em análise competitiva de 14 projetos similares + auto-crítica do código + papers recentes 2024-2025 sobre retrieval e memória de agentes. 证据：`ROADMAP.md`\n- **Describe the bug**（documentation）：A clear description of what is wrong. 证据：`.github/ISSUE_TEMPLATE/bug_report.md`\n- **Problem / motivation**（documentation）：What problem does this solve? Who benefits? 证据：`.github/ISSUE_TEMPLATE/feature_request.md`\n- **Manifest**（structured_config）：{ \"dxt version\": \"0.1\", \"name\": \"memorymesh\", \"display name\": \"MemoryMesh\", \"version\": \"0.1.0\", \"description\": \"Local MCP hub â€” semantic search over your personal files\", \"author\": { \"name\": \"Carlos Coelho\", \"email\": \"\" }, \"server\": { \"type\": \"binary\", \"entry point\": \"memorymesh.exe\", \"mcp config\": { \"command\": \"C:\\\\Users\\\\carlo\\\\Visual Studio Code\\\\eu\\\\memorymesh\\\\.venv\\\\Scripts\\\\memorymesh.exe\", \"args\": \"start\", \"--transport\", \"stdio\" } } } 证据：`memorymesh-extension/manifest.json`\n- **Manifest**（structured_config）：{ \"manifest version\": 3, \"name\": \"MemoryMesh\", \"version\": \"0.8.0\", \"description\": \"Search your MemoryMesh personal knowledge base from any webpage.\", \"permissions\": \"storage\", \"activeTab\" , \"host permissions\": \"http://127.0.0.1:8765/ \" , \"background\": { \"service worker\": \"background.js\", \"type\": \"module\" }, \"action\": { \"default popup\": \"popup/popup.html\", \"default title\": \"MemoryMesh Search\", \"default icon\": { \"16\": \"icons/icon16.svg\", \"48\": \"icons/icon48.svg\", \"128\": \"icons/icon128.svg\" } }, \"options page\": \"options/options.html\", \"content scripts\": { \"matches\": \" \" , \"js\": \"content/content.js\" , \"run at\": \"document idle\" } , \"icons\": { \"16\": \"icons/icon16.svg\", \"48\": \"icons/icon48.svg\", \"… 证据：`extensions/browser/manifest.json`\n- **Tsconfig**（structured_config）：{ \"compilerOptions\": { \"module\": \"commonjs\", \"target\": \"ES2022\", \"lib\": \"ES2022\" , \"outDir\": \"./out\", \"rootDir\": \"./src\", \"strict\": true, \"noImplicitAny\": true, \"sourceMap\": true, \"declaration\": true, \"esModuleInterop\": true, \"skipLibCheck\": true }, \"include\": \"src/ / \" , \"exclude\": \"node modules\", \".vscode-test\" } 证据：`extensions/vscode/tsconfig.json`\n- **Python**（source_file）：Python pycache / .py cod $py.class .so .egg .egg-info/ dist/ build/ .eggs/ .whl 证据：`.gitignore`\n- **.Pre Commit Config**（source_file）：repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.4.0 hooks: - id: ruff args: --fix - id: ruff-format 证据：`.pre-commit-config.yaml`\n- **── Build stage ───────────────────────────────────────────────────────────────**（source_file）：── Build stage ─────────────────────────────────────────────────────────────── Installs dependencies into a virtual environment that we copy to the final image. Keeps the final image small by excluding the uv tool itself. FROM python:3.11-slim AS builder 证据：`Dockerfile`\n- **Init**（source_file）：\"\"\"MemoryMesh benchmark scripts.\"\"\" 证据：`benchmarks/__init__.py`\n- **── Model catalogue ───────────────────────────────────────────────────────────**（source_file）：\"\"\"Embedding model comparison benchmark. 证据：`benchmarks/bench_embedding_models.py`\n- **Ensure src/ is in path when run without uv install**（source_file）：Measures how many files/chunks MemoryMesh can index per second using a synthetic corpus of configurable size. All real components are used ChromaDB, BM25, MetadataStore except the embedding provider, which is replaced with a deterministic mock to decouple indexing speed from GPU/CPU model inference speed. 证据：`benchmarks/bench_indexing.py`\n- **── Helpers ───────────────────────────────────────────────────────────────────**（source_file）：Measures p50 / p95 / p99 end-to-end search latency across hybrid, dense, and sparse modes. A synthetic corpus is indexed once; then each query is run n queries times and latencies are collected. 证据：`benchmarks/bench_search_latency.py`\n- **=============================================================================**（source_file）：============================================================================= MemoryMesh — Example configuration ============================================================================= Copy this file to ./config.yaml CWD or ~/.memorymesh/config.yaml Both ~ and ${ENV VAR} are expanded automatically. Anything you don't override falls back to the defaults below. ============================================================================= 证据：`config.example.yaml`\n- **─────────────────────────────────────────────────────────────────────────────**（source_file）：───────────────────────────────────────────────────────────────────────────── MemoryMesh — docker-compose.yml Quick start: cp .env.example .env set your paths and tokens docker compose up -d The MCP HTTP endpoint is available at http://127.0.0.1:8765 The health endpoint is at http://127.0.0.1:8766/health ───────────────────────────────────────────────────────────────────────────── 证据：`docker-compose.yml`\n- **install extension.ps1**（source_file）：install extension.ps1 Instala o MemoryMesh como extensao do Claude Desktop automaticamente. Uso: powershell -ExecutionPolicy Bypass -File install extension.ps1 证据：`install_extension.ps1`\n- **Benchmark scripts manipulate sys.path before local imports expected pattern .**（source_file）：project name = \"memorymesh-mcp\" version = \"0.8.0\" description = \"Local MCP hub for personal data — private, cross-platform, agent-ready.\" readme = \"README.md\" license = \"MIT\" authors = {name = \"Carlos Coelho\", email = \"kilhub.projects@gmail.com\"}, keywords = \"mcp\", \"embeddings\", \"search\", \"rag\", \"personal-data\", \"local-first\" classifiers = \"Development Status :: 3 - Alpha\", \"Intended Audience :: Developers\", \"License :: OSI Approved :: MIT License\", \"Operating System :: OS Independent\", \"Programming Language :: Python :: 3\", \"Programming Language :: Python :: 3.11\", \"Programming Language :: Python :: 3.12\", \"Topic :: Software Development :: Libraries :: Python Modules\", \"Topic :: Text Proce… 证据：`pyproject.toml`\n- **── Ground truth ──────────────────────────────────────────────────────────────**（source_file）：\"\"\"Wave 0 eval: compare baseline vs reranker+expansion on field-test queries. 证据：`scripts/eval_wave0.py`\n- **Conftest**（source_file）：\"\"\"Shared pytest fixtures and configuration for MemoryMesh tests.\"\"\" 证据：`tests/conftest.py`\n- **MemoryMesh validation script**（source_file）：MemoryMesh validation script Runs: uv sync, ruff check, pytest, benchmark imports 证据：`validate.ps1`\n- **!/usr/bin/env python**（source_file）：!/usr/bin/env python \"\"\"MemoryMesh validation runner — subprocess-based without relying on uv.\"\"\" 证据：`validate.py`\n\n## 宿主 AI 必须遵守的规则\n\n- **把本资产当作开工前上下文，而不是运行环境。**：AI Context Pack 只包含证据化项目理解，不包含目标项目的可执行状态。 证据：`README.md`, `CONTRIBUTING.md`, `extensions/vscode/package.json`\n- **回答用户时区分可预览内容与必须安装后才能验证的内容。**：安装前体验的消费者价值来自降低误装和误判，而不是伪装成真实运行。 证据：`README.md`, `CONTRIBUTING.md`, `extensions/vscode/package.json`\n\n## 用户开工前应该回答的问题\n\n- 你准备在哪个宿主 AI 或本地环境中使用它？\n- 你只是想先体验工作流，还是准备真实安装？\n- 你最在意的是安装成本、输出质量、还是和现有规则的冲突？\n\n## 验收标准\n\n- 所有能力声明都能回指到 evidence_refs 中的文件路径。\n- AI_CONTEXT_PACK.md 没有把预览包装成真实运行。\n- 用户能在 3 分钟内看懂适合谁、能做什么、如何开始和风险边界。\n\n---\n\n## Doramagic Context Augmentation\n\n下面内容用于强化 Repomix/AI Context Pack 主体。Human Manual 只提供阅读骨架；踩坑日志会被转成宿主 AI 必须遵守的工作约束。\n\n## Human Manual 骨架\n\n使用规则：这里只是项目阅读路线和显著性信号，不是事实权威。具体事实仍必须回到 repo evidence / Claim Graph。\n\n宿主 AI 硬性规则：\n- 不得把页标题、章节顺序、摘要或 importance 当作项目事实证据。\n- 解释 Human Manual 骨架时，必须明确说它只是阅读路线/显著性信号。\n- 能力、安装、兼容性、运行状态和风险判断必须引用 repo evidence、source path 或 Claim Graph。\n\n- **MemoryMesh 简介**：importance `high`\n  - source_paths: README.md, ROADMAP.md\n- **快速入门指南**：importance `high`\n  - source_paths: config.example.yaml, src/memorymesh/cli.py\n- **系统架构**：importance `high`\n  - source_paths: ARCHITECTURE.md, src/memorymesh/server/app.py, src/memorymesh/server/transports.py, src/memorymesh/indexer/file_indexer.py\n- **索引管道**：importance `high`\n  - source_paths: src/memorymesh/indexer/file_indexer.py, src/memorymesh/indexer/watcher.py, src/memorymesh/parsing/registry.py, src/memorymesh/embeddings/registry.py, src/memorymesh/storage/vector_store.py\n- **文件解析器**：importance `medium`\n  - source_paths: src/memorymesh/parsing/base.py, src/memorymesh/parsing/markdown.py, src/memorymesh/parsing/pdf.py, src/memorymesh/parsing/docx.py, src/memorymesh/parsing/obsidian_parser.py\n- **文本分块策略**：importance `medium`\n  - source_paths: src/memorymesh/chunking/base.py, src/memorymesh/chunking/recursive.py, src/memorymesh/chunking/markdown.py, src/memorymesh/chunking/code.py, src/memorymesh/chunking/registry.py\n- **搜索引擎**：importance `high`\n  - source_paths: src/memorymesh/search/engine.py, src/memorymesh/search/rank_fusion.py, src/memorymesh/search/query_expander.py, src/memorymesh/llm/ollama_client.py, src/memorymesh/server/tools/ask_memory.py\n- **结果重排序**：importance `medium`\n  - source_paths: src/memorymesh/search/reranker.py, src/memorymesh/core/models/config.py\n\n## Repo Inspection Evidence / 源码检查证据\n\n- repo_clone_verified: true\n- repo_inspection_verified: true\n- repo_commit: `bbf24d6918789e8e9eac56bdc2e11c606699ba4b`\n- inspected_files: `pyproject.toml`, `Dockerfile`, `README.md`, `docker-compose.yml`, `uv.lock`, `src/memorymesh/cli.py`, `src/memorymesh/__init__.py`, `src/memorymesh/config.py`, `src/memorymesh/__main__.py`, `src/memorymesh/embeddings/registry.py`, `src/memorymesh/embeddings/sentence_transformers_provider.py`, `src/memorymesh/embeddings/__init__.py`, `src/memorymesh/embeddings/cache.py`, `src/memorymesh/embeddings/base.py`, `src/memorymesh/llm/ollama_client.py`, `src/memorymesh/llm/__init__.py`, `src/memorymesh/connectors/mastodon_connector.py`, `src/memorymesh/connectors/gitlab_connector.py`, `src/memorymesh/connectors/_auth.py`, `src/memorymesh/connectors/bank_csv_connector.py`\n\n宿主 AI 硬性规则：\n- 没有 repo_clone_verified=true 时，不得声称已经读过源码。\n- 没有 repo_inspection_verified=true 时，不得把 README/docs/package 文件判断写成事实。\n- 没有 quick_start_verified=true 时，不得声称 Quick Start 已跑通。\n\n## Doramagic Pitfall Constraints / 踩坑约束\n\n这些规则来自 Doramagic 发现、验证或编译过程中的项目专属坑点。宿主 AI 必须把它们当作工作约束，而不是普通说明文字。\n\n### Constraint 1: 能力判断依赖假设\n\n- Trigger: README/documentation is current enough for a first validation pass.\n- Host AI rule: 将假设转成下游验证清单。\n- Why it matters: 假设不成立时，用户拿不到承诺的能力。\n- Evidence: capability.assumptions | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | README/documentation is current enough for a first validation pass.\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 2: 维护活跃度未知\n\n- Trigger: 未记录 last_activity_observed。\n- Host AI rule: 补 GitHub 最近 commit、release、issue/PR 响应信号。\n- Why it matters: 新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- Evidence: evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | last_activity_observed missing\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 3: 下游验证发现风险项\n\n- Trigger: no_demo\n- Host AI rule: 进入安全/权限治理复核队列。\n- Why it matters: 下游已经要求复核，不能在页面中弱化。\n- Evidence: downstream_validation.risk_items | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | no_demo; severity=medium\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 4: 存在评分风险\n\n- Trigger: no_demo\n- Host AI rule: 把风险写入边界卡，并确认是否需要人工复核。\n- Why it matters: 风险会影响是否适合普通用户安装。\n- Evidence: risks.scoring_risks | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | no_demo; severity=medium\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 5: issue/PR 响应质量未知\n\n- Trigger: issue_or_pr_quality=unknown。\n- Host AI rule: 抽样最近 issue/PR，判断是否长期无人处理。\n- Why it matters: 用户无法判断遇到问题后是否有人维护。\n- Evidence: evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | issue_or_pr_quality=unknown\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 6: 发布节奏不明确\n\n- Trigger: release_recency=unknown。\n- Host AI rule: 确认最近 release/tag 和 README 安装命令是否一致。\n- Why it matters: 安装命令和文档可能落后于代码，用户踩坑概率升高。\n- Evidence: evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | release_recency=unknown\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n",
      "summary": "给宿主 AI 的上下文和工作边界。",
      "title": "AI Context Pack / 带给我的 AI"
    },
    "boundary_risk_card": {
      "asset_id": "boundary_risk_card",
      "filename": "BOUNDARY_RISK_CARD.md",
      "markdown": "# Boundary & Risk Card / 安装前决策卡\n\n项目：kilhubprojects/memory-mesh\n\n## Doramagic 试用结论\n\n当前结论：可以进入发布前推荐检查；首次使用仍应从最小权限、临时目录和可回滚配置开始。\n\n## 用户现在可以做\n\n- 可以先阅读 Human Manual，理解项目目的和主要工作流。\n- 可以复制 Prompt Preview 做安装前体验；这只验证交互感，不代表真实运行。\n- 可以把官方 Quick Start 命令放到隔离环境中验证，不要直接进主力环境。\n\n## 现在不要做\n\n- 不要把 Prompt Preview 当成项目实际运行结果。\n- 不要把 metadata-only validation 当成沙箱安装验证。\n- 不要把未验证能力写成“已支持、已跑通、可放心安装”。\n- 不要在首次试用时交出生产数据、私人文件、真实密钥或主力配置目录。\n\n## 安装前检查\n\n- 宿主 AI 是否匹配：mcp_host\n- 官方安装入口状态：已发现官方入口\n- 是否在临时目录、临时宿主或容器中验证：必须是\n- 是否能回滚配置改动：必须能\n- 是否需要 API Key、网络访问、读写文件或修改宿主配置：未确认前按高风险处理\n- 是否记录了安装命令、实际输出和失败日志：必须记录\n\n## 当前阻塞项\n\n- review_required: community_discussion_evidence_below_public_threshold\n\n## 项目专属踩坑\n\n- 能力判断依赖假设（medium）：假设不成立时，用户拿不到承诺的能力。 建议检查：将假设转成下游验证清单。\n- 维护活跃度未知（medium）：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 下游验证发现风险项（medium）：下游已经要求复核，不能在页面中弱化。 建议检查：进入安全/权限治理复核队列。\n- 存在评分风险（medium）：风险会影响是否适合普通用户安装。 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- issue/PR 响应质量未知（low）：用户无法判断遇到问题后是否有人维护。 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n\n## 风险与权限提示\n\n- no_demo: medium\n\n## 证据缺口\n\n- 暂未发现结构化证据缺口。\n",
      "summary": "安装、权限、验证和推荐前风险。",
      "title": "Boundary & Risk Card / 边界与风险卡"
    },
    "human_manual": {
      "asset_id": "human_manual",
      "filename": "HUMAN_MANUAL.md",
      "markdown": "# https://github.com/kilhubprojects/memory-mesh 项目说明书\n\n生成时间：2026-05-15 00:17:37 UTC\n\n## 目录\n\n- [MemoryMesh 简介](#page-introduction)\n- [快速入门指南](#page-quickstart)\n- [系统架构](#page-architecture)\n- [索引管道](#page-indexing-pipeline)\n- [文件解析器](#page-parsers)\n- [文本分块策略](#page-chunkers)\n- [搜索引擎](#page-search-engine)\n- [结果重排序](#page-reranking)\n- [数据连接器](#page-connectors)\n- [MCP 工具参考](#page-mcp-tools)\n\n<a id='page-introduction'></a>\n\n## MemoryMesh 简介\n\n### 相关页面\n\n相关主题：[快速入门指南](#page-quickstart), [系统架构](#page-architecture)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/server/dashboard.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/dashboard.py)\n- [src/memorymesh/connectors/roam_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/roam_connector.py)\n- [src/memorymesh/connectors/logseq_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\n- [src/memorymesh/parsing/obsidian_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/obsidian_parser.py)\n- [src/memorymesh/parsing/notion_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/notion_parser.py)\n- [src/memorymesh/connectors/confluence_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/confluence_connector.py)\n- [src/memorymesh/chunking/markdown.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/markdown.py)\n- [src/memorymesh/chunking/code.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/code.py)\n- [src/memorymesh/storage/file_repository.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/storage/file_repository.py)\n- [src/memorymesh/core/models/config.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/config.py)\n- [src/memorymesh/core/models/chunk.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/chunk.py)\n- [src/memorymesh/server/rest_api.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/rest_api.py)\n- [CHANGELOG.md](https://github.com/kilhubprojects/memory-mesh/blob/main/CHANGELOG.md)\n</details>\n\n# MemoryMesh 简介\n\nMemoryMesh 是一个模块化的本地知识检索与记忆管理框架，专为 AI 智能体（Agent）设计。它通过统一的多源连接器体系、层级化记忆管理、增量索引管道和灵活的 API 接口，使 AI 能够持久化访问和检索用户的个人知识库，同时保持所有数据的本地化存储。\n\n## 系统架构\n\nMemoryMesh 采用分层架构，从底向上依次为存储层、索引层、检索层、连接器层和服务层。各层职责清晰，通过明确定义的接口进行通信。\n\n```mermaid\ngraph TD\n    subgraph 服务层\n        A[REST API]\n        B[MCP 工具]\n        C[Web Dashboard]\n        D[Health Server]\n    end\n    \n    subgraph 连接器层\n        E[Roam Connector]\n        F[Logseq Connector]\n        G[Notion Parser]\n        H[Obsidian Parser]\n        I[Confluence Connector]\n    end\n    \n    subgraph 索引与检索层\n        J[FileIndexer]\n        K[SearchEngine]\n        L[QueryExpander]\n        M[Reranker]\n    end\n    \n    subgraph 记忆管理层\n        N[TieredMemoryManager]\n        O[EpisodicMemory]\n        P[EntityExtractor]\n    end\n    \n    subgraph 存储层\n        Q[MetadataStore SQLite]\n        R[EmbeddingProvider]\n        S[VectorStore]\n    end\n    \n    A --> N\n    B --> N\n    C --> Q\n    D --> Q\n    E --> J\n    F --> J\n    G --> J\n    H --> J\n    I --> J\n    J --> Q\n    J --> R\n    R --> S\n    K --> S\n    K --> L\n    L --> M\n    N --> Q\n    O --> Q\n    P --> Q\n```\n\n资料来源：[src/memorymesh/server/dashboard.py:1-50]()\n\n## 核心模块\n\n### 连接器体系\n\nMemoryMesh 通过统一的连接器接口对接多种知识管理工具，实现文档的自动采集与解析。\n\n| 连接器 | 数据源 | 解析格式 | 关键特性 |\n|--------|--------|----------|----------|\n| RoamConnector | Roam Research JSON 导出 | 递归块扁平化 | WikiLink 提取、日期过滤 |\n| LogseqConnector | Logseq 图谱目录 | Markdown | 块引用转换、属性提取 |\n| NotionParser | Notion HTML 导出 | SAX 解析 | UUID 提取、数据库属性 |\n| ObsidianParser | Obsidian 库 | Markdown | YAML frontmatter、backlink |\n| ConfluenceConnector | Confluence Cloud REST API | HTML | 空间过滤、偏移分页 |\n\n资料来源：[src/memorymesh/connectors/roam_connector.py:1-30]()\n\n#### Roam Research 连接器\n\nRoamConnector 解析 Roam Research 的 JSON 导出文件，将嵌套的块树结构扁平化为纯文本。它会依次应用正则模式去除 Roam 特有语法：\n\n- `{{[[...]]}}` 模板引用\n- `[[...]]` 页面引用\n- `#[[...]]` / `#tag` 标签语法\n\n```python\n_ROAM_PATTERNS: list[re.Pattern[str]] = [\n    re.compile(r\"\\{\\{(\\[\\[.*?\\]\\])?\\}\\}\"),\n    re.compile(r\"\\[\\[([^\\]]+)\\]\\]\"),\n    re.compile(r\"#\\[\\[([^\\]]+)\\]\\]\"),\n]\n```\n\n资料来源：[src/memorymesh/connectors/roam_connector.py:30-35]()\n\n#### Logseq 连接器\n\nLogseqConnector 读取图谱目录下的 `pages/` 和 `journals/` 子目录，处理以下 Logseq 特有语法：\n\n| 语法模式 | 转换结果 |\n|----------|----------|\n| `((uuid))` 块引用 | `[block]` |\n| `{{embed [[Page]]}}` 嵌入 | `[embed: Page]` |\n| `{{query ...}}` 查询块 | 完全移除 |\n| `key:: value` 属性行 | 提取至元数据 |\n\n```python\n_RE_BLOCK_REF = re.compile(r\"\\(\\([0-9a-f-]{36}\\)\\)\")\n_RE_EMBED = re.compile(r\"\\{\\{embed\\s+\\[\\[([^\\]]+)\\]\\]\\}\\}\")\n_RE_QUERY = re.compile(r\"\\{\\{query[^}]*\\}\\}\")\n```\n\n资料来源：[src/memorymesh/connectors/logseq_connector.py:35-40]()\n\n#### Notion 解析器\n\nNotionParser 基于标准库 `html.parser` 实现 SAX 风格的解析，无需外部依赖。它从导出的 HTML 文件中提取：\n\n- `<title>` 标签内容\n- `<h1>` 可见页面标题\n- `data-type` 属性（数据库属性类型）\n- 可见正文文本（去除标记）\n\n文件名中嵌入的 UUID 用于唯一标识页面：`Page Title a1b2c3...html`\n\n资料来源：[src/memorymesh/parsing/notion_parser.py:1-40]()\n\n#### Obsidian 解析器\n\nObsidianParser 扩展标准 Markdown 解析，增加以下能力：\n\n- **YAML Frontmatter 提取**：解析 `---` 分隔符之间的元数据\n- **WikiLink Backlink 提取**：通过 `[[link]]` 和 `[[link|alias]]` 模式\n- **标签解析**：支持 `tags:` 字段和内联 `#tag` 语法\n\n```python\n_FRONTMATTER_RE = re.compile(\n    r\"^---\\r?\\n(.*?)\\r?\\n(?:---|\\.\\.\\.)(?:\\r?\\n|$)\",\n    re.DOTALL,\n)\n_WIKILINK_RE = re.compile(r\"(?<!!)\\[\\[([^\\[\\]|#]+?)(?:\\|[^\\[\\]]*?)?\\]\\]\")\n```\n\n资料来源：[src/memorymesh/parsing/obsidian_parser.py:15-25]()\n\n#### Confluence 连接器\n\nConfluenceConnector 通过 REST API 与 Confluence Cloud 交互，支持：\n\n- **偏移分页**：通过 `start` / `limit` 参数遍历所有页面\n- **空间过滤**：通过 `space_keys` 参数限定特定空间\n- **HTML 净化**：将 `storage` 格式页面体转换为纯文本\n- **HTTP Basic 认证**：使用 `email:api_token` 格式\n\n```python\nconnector = ConfluenceConnector(ConfluenceConfig(\n    base_url=\"https://myorg.atlassian.net\",\n    email=\"me@example.com\",\n    api_token=SecretStr(\"my-token\"),\n    space_keys=[\"ENG\", \"DOCS\"],\n    days_past=90,\n))\n```\n\n资料来源：[src/memorymesh/connectors/confluence_connector.py:1-50]()\n\n### 文档分块策略\n\nMemoryMesh 实现了多种分块器（Chunker），将解析后的文档拆分为可索引的语义单元。\n\n| 分块器 | 适用场景 | 特性 |\n|--------|----------|------|\n| RecursiveChunker | 通用文本 | 递归字符级分割，支持 overlap |\n| MarkdownChunker | Markdown 文档 | 基于 ATX 标题分割 |\n| CodeChunker | 源代码文件 | 基于 AST 节点分割 |\n\n```mermaid\ngraph LR\n    A[ParsedDocument] --> B{Markdown?}\n    B -->|是| C[MarkdownChunker]\n    B -->|否| D{Code?}\n    D -->|是| E[CodeChunker]\n    D -->|否| F[RecursiveChunker]\n    \n    C --> G[Chunk 列表]\n    E --> G\n    F --> G\n```\n\n资料来源：[src/memorymesh/chunking/markdown.py:1-20]()\n\n#### Markdown 分块器\n\nMarkdownChunker 按 ATX 标题（`#`, `##`, …）分割文档，每个分块包含一个章节：标题行及其下方正文。超过 `max_chunk_size` 的章节由递归分块器进一步分割。\n\n`heading_path` 元数据字段记录完整的祖先标题栈，便于搜索命中时精确定位文档位置。\n\n资料来源：[src/memorymesh/chunking/markdown.py:15-40]()\n\n#### 代码分块器\n\nCodeChunker 利用 `tree-sitter` 解析 AST，提取函数、类等节点。每个节点生成一个分块，附带 `function_name`、`class_name` 和 `language` 元数据。未识别的顶级代码作为残差分块处理。\n\n```python\nchunks.append(\n    Chunk(\n        path=doc.path,\n        chunk_index=idx,\n        text=sub.text,\n        metadata=ChunkMetadata(\n            language=lang_name,\n            function_name=func_name,\n            class_name=class_name,\n        ),\n    )\n)\n```\n\n资料来源：[src/memorymesh/chunking/code.py:50-70]()\n\n### 层级化记忆管理\n\nMemoryMesh 的 `TieredMemoryManager` 将记忆划分为三个温度层级，实现类似于人类记忆的遗忘曲线管理。\n\n| 层级 | 描述 | 存储位置 |\n|------|------|----------|\n| Hot | 最近访问或手动固定的内容 | RAM 缓存 |\n| Warm | 正常索引的内容（默认） | 向量数据库 |\n| Cold | 罕见访问的内容 | 压缩存储，衰减评分 |\n\n```python\nclass MemoryTier(StrEnum):\n    hot = \"hot\"\n    warm = \"warm\"\n    cold = \"cold\"\n```\n\n资料来源：[src/memorymesh/core/models/config.py:40-50]()\n\n#### 记忆分层工作流\n\n```mermaid\ngraph TD\n    A[新索引内容] --> B{Hot 层}\n    B --> C[频繁访问?]\n    C -->|是| D[保持在 Hot]\n    C -->|否| E[移至 Warm]\n    E --> F{遗忘策略}\n    F --> G{访问频率低}\n    G -->|是| H[移至 Cold]\n    G -->|否| I[保持在 Warm]\n    H --> J[评分衰减]\n    J --> K{超过阈值?}\n    K -->|是| L[遗忘 Chunk]\n```\n\n资料来源：[src/memorymesh/server/rest_api.py:1-30]()\n\n### 实体提取\n\n当配置 `memory.entity_extraction.enabled: true` 且 Ollama 运行中时，`FileIndexer` 会在每个文件索引后自动提取实体并持久化。\n\n实体记录包含：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| name | string | 实体名称 |\n| entity_type | string | 实体类型（如人物、地点、组织） |\n| mention_count | int | 提及次数 |\n\n资料来源：[src/memorymesh/server/dashboard.py:80-100]()\n\n### 情景记忆\n\nEpisodicMemory 记录索引过程中的关键事件，用于时间线可视化和审计。\n\n事件记录包含：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| timestamp | float | Unix 时间戳 |\n| event_type | string | 事件类型 |\n| source | string | 来源标识 |\n| chunk_ids | list[str] | 关联的分块 ID 列表 |\n\n```python\nevents = ctx.metadata_store.list_episodic_events(since=since_ts, limit=100)\n```\n\n资料来源：[src/memorymesh/server/dashboard.py:60-75]()\n\n## 数据模型\n\n### Chunk 模型\n\nChunk 是 MemoryMesh 的核心数据单元，代表文档的一个可索引片段。\n\n```python\nclass Chunk(BaseModel):\n    path: Path                    # 文档路径\n    chunk_index: int              # 分块序号\n    text: str                     # 分块文本内容\n    start_char: int               # 起始字符偏移\n    end_char: int                 # 结束字符偏移\n    file_type: str = \"\"           # 文件类型扩展名\n    mtime: float = 0.0            # 文件修改时间\n    source_root: str = \"\"         # 源根目录路径\n    metadata: ChunkMetadata       # 分块元数据\n    \n    @property\n    def id(self) -> str:\n        return f\"{self.path}:{self.chunk_index}\"\n```\n\n资料来源：[src/memorymesh/core/models/chunk.py:30-50]()\n\n### ChunkMetadata 模型\n\n```python\nclass ChunkMetadata(ConfigDict):\n    heading_path: str = \"\"         # 完整标题路径（Markdown）\n    language: str = \"\"            # 编程语言（代码块）\n    function_name: str = \"\"       # 函数名（代码块）\n    class_name: str = \"\"          # 类名（代码块）\n    backlinks: list[str] = []     # 反向链接列表\n    chunk_type: str = \"\"          # 分块类型标识\n```\n\n资料来源：[src/memorymesh/core/models/chunk.py:15-25]()\n\n### FileRecord 模型\n\nFileRecord 记录每个被索引文件的状态信息。\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| path | string | 绝对路径（主键） |\n| source_name | string | 所属源名称 |\n| sha256 | string | 内容 SHA-256 哈希 |\n| mtime | float | 文件修改时间 |\n| size_bytes | int | 文件大小 |\n| file_type | string | 标准化扩展名 |\n| n_chunks | int | 生成的分块数量 |\n| status | string | 状态（indexed/parse_error/unsupported/deleted/pending_reindex） |\n| error_message | string | 最后一次失败描述 |\n| indexed_at | float | 最后索引时间戳 |\n| embedding_model_id | string | 使用的嵌入模型 ID |\n\n资料来源：[src/memorymesh/storage/file_repository.py:15-35]()\n\n## 服务端组件\n\n### REST API\n\nMemoryMesh 提供基于 FastAPI 的 RESTful API，支持以下核心操作：\n\n| 端点 | 方法 | 说明 | 权限要求 |\n|------|------|------|----------|\n| `/api/search` | GET | 搜索记忆内容 | read |\n| `/api/sources` | GET | 列出所有数据源 | read |\n| `/api/chunks` | GET | 获取分块详情 | read |\n| `/api/memory/promote` | POST | 提升分块至热层 | write |\n| `/api/memory/forget` | POST | 遗忘分块 | delete |\n\n#### 遗忘操作\n\n遗忘操作将分块降至冷层，使其相关性评分随时间衰减，而非立即删除。\n\n```python\nRequest body: {\"chunk_id\": \"<path>:<chunk_index>\"}\n\n@app.post(\"/api/memory/forget\")\nasync def forget_chunk(body: dict) -> dict:\n    app_ctx.metadata_store.forget_chunk(chunk_id)\n    return {\"status\": \"forgotten\", \"chunk_id\": chunk_id}\n```\n\n资料来源：[src/memorymesh/server/rest_api.py:20-40]()\n\n### Web Dashboard\n\nDashboard 是基于 FastAPI + HTMX 的单页应用，运行于 `:8767` 端口。\n\n| 页面 | 路由 | 功能 |\n|------|------|------|\n| 数据源 | `/` | 列出所有配置的源目录及文件统计 |\n| 搜索 | `/search` | 全文搜索界面，支持稀疏/密集模式切换 |\n| 记忆层级 | `/tiers` | 热/温/冷分块分布统计 |\n| 实体 | `/entities` | 提取的实体列表及类型 |\n| 时间线 | `/timeline` | 情景记忆事件时间轴 |\n| 知识图谱 | `/graph-ui` | 可视化节点关系图 |\n\n```python\n@app.get(\"/tiers\", response_class=HTMLResponse)\nasync def tiers_page() -> str:\n    counts: dict[str, int] = {}\n    for tier in MemoryTier:\n        entries = ctx.metadata_store.list_chunks_by_tier(tier, limit=None)\n        counts[tier.value] = len(entries)\n    # ...\n```\n\n资料来源：[src/memorymesh/server/dashboard.py:100-130]()\n\n### Health Server\n\nHealth Server 提供系统健康检查端点，运行于 `:8766` 端口，在守护进程启动时自动启用，退出时干净关闭。\n\n资料来源：[CHANGELOG.md:20-25]()\n\n## 搜索架构\n\nMemoryMesh 的搜索管道采用多阶段检索与重排序架构。\n\n```mermaid\ngraph LR\n    A[用户查询] --> B[QueryExpander]\n    B --> C[词汇变体生成]\n    C --> D[并行检索]\n    D --> E[密集检索]\n    D --> F[稀疏检索]\n    E --> G[FuseResults]\n    F --> G\n    G --> H[SearchReranker]\n    H --> I[Top-K 结果]\n```\n\n| 组件 | 说明 | 配置项 |\n|------|------|--------|\n| QueryExpander | 生成查询词汇变体 | `n_lexical_variants` |\n| SearchReranker | 重排序候选结果 | `top_k_before_rerank` |\n| SentenceTransformers | 密集向量检索 | `model_id` |\n\n### 搜索配置\n\n| 参数 | 默认值 | 说明 |\n|------|--------|------|\n| `top_k_before_rerank` | 35 | 重排序前保留的候选数量 |\n| `n_lexical_variants` | 1 | 查询扩展词汇变体数量 |\n\n资料来源：[CHANGELOG.md:30-40]()\n\n## 配置体系\n\nMemoryMesh 通过 YAML 配置文件管理所有设置。\n\n### 核心配置结构\n\n```yaml\nsources:\n  - name: \"my-vault\"\n    path: \"~/Obsidian/vault\"\n    recursive: true\n    extensions: [\".md\", \".py\"]\n\nmemory:\n  tiers:\n    enabled: true\n  forgetting:\n    enabled: true\n  entity_extraction:\n    enabled: true\n  episodic:\n    enabled: true\n\nembeddings:\n  provider: \"sentence_transformers\"\n  model_id: \"all-MiniLM-L6-v2\"\n\nsearch:\n  reranker:\n    top_k_before_rerank: 35\n  query_expansion:\n    n_lexical_variants: 1\n```\n\n资料来源：[src/memorymesh/core/models/config.py:50-80]()\n\n### 代理权限\n\n```python\nclass AgentPermission(StrEnum):\n    read = \"read\"\n    read_index = \"read+index\"\n    read_index_delete = \"read+index+delete\"\n    admin = \"admin\"\n```\n\n资料来源：[src/memorymesh/core/models/config.py:55-65]()\n\n## 索引流程\n\n```mermaid\nsequenceDiagram\n    participant C as Connector\n    participant P as Parser\n    participant CK as Chunker\n    participant I as FileIndexer\n    participant M as MetadataStore\n    participant E as EmbeddingProvider\n    \n    C->>P: fetch_documents()\n    P->>P: parse(path)\n    P-->>I: ParsedDocument\n    I->>CK: chunk(doc)\n    CK-->>I: List[Chunk]\n    I->>E: embed(chunks)\n    E-->>I: List[ChunkWithEmbedding]\n    I->>M: upsert_file()\n    I->>M: upsert_chunks()\n    I->>M: add_episodic_event()\n```\n\n### 索引管道关键步骤\n\n1. **连接器采集**：从各数据源获取原始文档\n2. **解析转换**：将原始格式转换为 `ParsedDocument`\n3. **分块处理**：按策略分割为语义单元\n4. **向量化**：通过 EmbeddingProvider 生成向量表示\n5. **持久化**：写入 SQLite 元数据存储和向量数据库\n6. **事件记录**：写入情景记忆事件\n\n## 版本演进\n\nMemoryMesh 采用语义化版本控制，主要版本功能如下：\n\n| 版本 | 日期 | 核心特性 |\n|------|------|----------|\n| 0.5.0 | 2026-05-03 | MVP 基线：SQLite、CLI、句子嵌入 |\n| 0.6.0 | 2026-05-10 | 层级记忆、Dashboard、授权体系、实体提取、CLIP 图像索引 |\n\n### 0.6.0 新增功能\n\n- **TieredMemoryManager**：层级化记忆管理，替代原有的简单存储\n- **DashboardServer**：FastAPI + HTMX Web 界面\n- **Auth Guard**：MCP 工具统一授权检查\n- **Entity Extraction**：Ollama 驱动的实体识别\n- **Health Server**：健康检查端点\n\n资料来源：[CHANGELOG.md:1-50]()\n\n## 技术栈\n\n| 层级 | 技术选型 |\n|------|----------|\n| 核心框架 | Python 3.11+ |\n| Web 框架 | FastAPI + HTMX |\n| 数据库 | SQLite3 |\n| 向量检索 | Sentence-Transformers |\n| CLI | Click |\n| 配置 | Pydantic + YAML |\n| 日志 | Loguru |\n| 代码解析 | tree-sitter |\n\n资料来源：[src/memorymesh/server/dashboard.py:1-20]()\n\n## 快速入门\n\n### 安装依赖\n\n```bash\nuv add memorymesh\nuv add 'fastapi[standard]'  # 可选：启用 Dashboard\n```\n\n### 配置数据源\n\n```yaml\n# config.yaml\nsources:\n  - name: \"obsidian-vault\"\n    path: \"~/Obsidian/my-vault\"\n    type: \"obsidian\"\n\nmemory:\n  tiers:\n    enabled: true\n  entity_extraction:\n    enabled: true\n```\n\n### 启动服务\n\n```bash\nmemorymesh start  # 启动守护进程\nmemorymesh index  # 执行索引任务\n```\n\n### 访问 Dashboard\n\n服务启动后访问 `http://localhost:8767` 查看：\n\n- 所有数据源的索引状态\n- 全文搜索界面\n- 记忆层级分布\n- 提取的实体列表\n- 情景记忆时间线\n\n---\n\n<a id='page-quickstart'></a>\n\n## 快速入门指南\n\n### 相关页面\n\n相关主题：[MemoryMesh 简介](#page-introduction)\n\n```json\n{\n  \"response\": \"# 快速入门指南\\n\\n<details>\\n<summary>相关源码文件</summary>\\n\\n以下源码文件用于生成本页说明：\\n\\n- [config.example.yaml](https://github.com/kilhubprojects/memory-mesh/blob/main/config.example.yaml)\\n- [src/memorymesh/cli.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/cli.py)\\n- [src/memorymesh/config.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/config.py)\\n- [src/memorymesh/core/models/config.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/config.py)\\n- [src/memorymesh/connectors/logseq_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\\n- [src/memorymesh/connectors/confluence_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/confluence_connector.py)\\n- [src/memorymesh/server/dashboard.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/dashboard.py)\\n- [CHANGELOG.md](https://github.com/kilhubprojects/memory-mesh/blob/main/CHANGELOG.md)\\n\\n</details>\\n\\n# 快速入门指南\\n\\n## 概述\\n\\nMemoryMesh 是一个本地优先的个人知识图谱和记忆管理系统，支持从多种数据源（Obsidian、Logseq、Notion、Confluence、Roam Research 等）索引文档，并通过 Ollama 提供的本地 LLM 实现语义搜索、实体提取和记忆分层管理。\\n\\n本指南将帮助你在几分钟内完成安装、配置和首次索引操作。\\n\\n## 系统要求\\n\\n| 组件 | 最低要求 | 推荐配置 |\\n|------|----------|----------|\\n| Python | 3.10+ | 3.11+ |\\n| 内存 | 4 GB | 8 GB+ |\\n| 磁盘 | 1 GB 可用空间 | SSD |\\n| Ollama | 可选（用于 AI 功能） | 最新版 |\\n\\n## 安装\\n\\n### 方式一：pip 安装\\n\\n```bash\\npip install memorymesh\\n```\\n\\n### 方式二：从源码安装\\n\\n```bash\\ngit clone https://github.com/kilhubprojects/memory-mesh.git\\ncd memory-mesh\\npip install -e .\\n```\\n\\n### 安装可选依赖\\n\\n```bash\\n# 支持 FastAPI 仪表盘\\npip install \\\"fastapi[standard]\\\"\\n\\n# 支持 Ollama 集成\\npip install ollama\\n\\n# 支持邮件解析\\npip install mailbox\\n\\n# 支持日历解析\\npip install icalendar>=5.0\\n```\\n\\n## 配置文件\\n\\nMemoryMesh 支持从 YAML 配置文件加载所有设置。默认搜索路径按以下优先级：\\n\\n1. `./config.yaml`（当前工作目录）\\n2. `~/.memorymesh/config.yaml`\\n\\n### 基础配置示例\\n\\n```yaml\\n# config.example.yaml\\nsources:\\n  - name: my-notes\\n    type: obsidian\\n    path: ~/Documents/Obsidian\\n    enabled: true\\n\\nembeddings:\\n  model: sentence-transformers/all-MiniLM-L6-v2\\n\\nserver:\\n  host: 0.0.0.0\\n  port: 8765\\n\\nollama:\\n  enabled: true\\n  base_url: http://localhost:11434\\n  model: llama3.2\\n```\\n\\n### 数据源配置详解\\n\\n| 参数 | 类型 | 默认值 | 说明 |\\n|------|------|--------|------|\\n| `name` | string | 必填 | 数据源唯一标识名称 |\\n| `type` | string | 必填 | 数据源类型：`obsidian`、`logseq`、`notion`、`confluence`、`roam` 等 |\\n| `path` | string | 必填 | 本地路径或远程 URL |\\n| `enabled` | bool | true | 是否启用该数据源 |\\n| `ignore_patterns` | list | 空 | 忽略的文件匹配模式 |\\n\\n资料来源：[src/memorymesh/core/models/config.py:1-80]()\\n\\n### 完整配置结构\\n\\n```yaml\\nmemorymesh:\\n  sources: []                    # 数据源列表\\n  global_ignore: []              # 全局忽略模式\\n  embeddings:                    # 向量化配置\\n    model: ...\\n    device: auto\\n  chunking:                      # 分块配置\\n    max_chunk_size: 800\\n    chunk_overlap: 50\\n  ocr:\\n    enabled: false\\n  search:\\n    top_k: 10\\n  storage:\\n    db_path: ~/.memorymesh/memory.db\\n  server:\\n    transport: uvicorn\\n    host: 0.0.0.0\\n    port: 8765\\n  ollama:\\n    enabled: false\\n    base_url: http://localhost:11434\\n    model: llama3.2\\n  memory:\\n    episodic:\\n      enabled: true\\n    tiers:\\n      hot_days: 7\\n      warm_days: 30\\n      cold_days: 90\\n    entity_extraction:\\n      enabled: false\\n```\\n\\n资料来源：[src/memorymesh/config.py:1-100]()\\n\\n## CLI 命令行工具\\n\\n### 启动守护进程\\n\\n```bash\\nmemorymesh start\\n```\\n\\n守护进程将：\\n\\n- 启动 API 服务器（默认端口 8765）\\n- 启动健康检查服务器（默认端口 8766）\\n- 启动 Web 仪表盘服务器（默认端口 8767）\\n- 监控文件系统变更（如果 watcher 启用）\\n\\n### 索引命令\\n\\n```bash\\n# 索引所有已配置的数据源\\nmemorymesh index\\n\\n# 索引指定数据源\\nmemorymesh index --source my-notes\\n\\n# 查看索引状态\\nmemorymesh status\\n```\\n\\n### 搜索命令\\n\\n```bash\\nmemorymesh search \\\"你的搜索关键词\\\"\\n```\\n\\n### 清理命令\\n\\n```bash\\n# 清理数据库\\nmemorymesh clean\\n\\n# 重置所有数据\\nmemorymesh reset\\n```\\n\\n资料来源：[src/memorymesh/cli.py:1-200]()\\n\\n## 数据源连接器\\n\\n### Obsidian 连接器\\n\\n支持从 Obsidian 保险库导入 Markdown 文件，自动提取：\\n\\n- YAML 前言（tags、aliases、created、modified）\\n- `[[wikilinks]]` 作为反向链接\\n- 嵌入的图像链接会被过滤\\n\\n```yaml\\nsources:\\n  - name: obsidian-vault\\n    type: obsidian\\n    path: ~/Obsidian/vault\\n```\\n\\n资料来源：[src/memorymesh/parsing/obsidian_parser.py:1-80]()\\n\\n### Logseq 连接器\\n\\n支持从 Logseq 图形目录导入，自动处理：\\n\\n- `((uuid))` 块引用 → `[block]`\\n- `{{embed [[Page]]}}` 嵌入 → `[embed: Page]`\\n- `{{query ...}}` 查询块（移除）\\n- `key:: value` 属性行（提取到元数据）\\n\\n```yaml\\nsources:\\n  - name: logseq-graph\\n    type: logseq\\n    path: ~/Logseq/my-graph\\n    config:\\n      pages_dir: pages\\n      journals_dir: journals\\n```\\n\\n资料来源：[src/memorymesh/connectors/logseq_connector.py:1-100]()\\n\\n### Notion 连接器\\n\\n支持解析 Notion HTML 导出文件，提取：\\n\\n- 页面标题（`<h1>` 或 `<title>`）\\n- 数据库属性块（`data-type` 属性）\\n- 页面 UUID（从文件名提取）\\n\\n```yaml\\nsources:\\n  - name: notion-export\\n    type: notion\\n    path: ~/Downloads/notion-export\\n```\\n\\n资料来源：[src/memorymesh/parsing/notion_parser.py:1-80]()\\n\\n### Confluence 连接器\\n\\n支持从 Confluence Cloud 拉取页面，支持：\\n\\n- 空间过滤（`space_keys`）\\n- 日期过滤（`days_past`）\\n- HTML 转纯文本\\n\\n```yaml\\nsources:\\n  - name: confluence-docs\\n    type: confluence\\n    config:\\n      base_url: https://myorg.atlassian.net\\n      email: me@example.com\\n      api_token: ${CONFLUENCE_API_TOKEN}\\n      space_keys:\\n        - ENG\\n        - DOCS\\n      days_past: 90\\n```\\n\\n资料来源：[src/memorymesh/connectors/confluence_connector.py:1-80]()\\n\\n### Roam Research 连接器\\n\\n支持解析 Roam Research JSON 导出，自动清理：\\n\\n- `{{[[...]]}}` 模板引用\\n- `[[...]]` 页面引用\\n- `#[[...]]` / `#tag` 标签语法\\n\\n```yaml\\nsources:\\n  - name: roam-export\\n    type: roam\\n    path: ~/Downloads/roam-export.json\\n    config:\\n      days_past: 365\\n```\\n\\n## 架构流程\\n\\n```mermaid\\ngraph TD\\n    A[配置文件 config.yaml] --> B[ConfigLoader]\\n    B --> C[MemoryMeshConfig 验证]\\n    C --> D[数据源连接器]\\n    D --> E[文档解析器]\\n    E --> F[分块处理器]\\n    F --> G[向量化引擎]\\n    G --> H[SQLite 元数据库]\\n    H --> I[搜索服务]\\n    I --> J[API / CLI / Web UI]\\n    \\n    D --> D1[Obsidian]\\n    D --> D2[Logseq]\\n    D --> D3[Notion]\\n    D --> D4[Confluence]\\n    D --> D5[Roam]\\n    \\n    G --> G1[SentenceTransformers]\\n    G --> G2[Ollama 本地 LLM]\\n    \\n    I --> I1[语义搜索]\\n    I --> I2[关键词搜索]\\n    I --> I3[混合检索]\\n```\\n\\n## 启动流程\\n\\n```mermaid\\nsequenceDiagram\\n    participant User\\n    participant CLI\\n    participant Config\\n    participant AppContext\\n    participant Server\\n    \\n    User->>CLI: memorymesh start\\n    CLI->>Config: load_config()\\n    Config-->>CLI: MemoryMeshConfig\\n    CLI->>AppContext: _load_context(cfg)\\n    AppContext->>AppContext: 初始化 MetadataStore\\n    AppContext->>AppContext: 初始化 EmbeddingProvider\\n    AppContext->>AppContext: 初始化 TieredMemoryManager\\n    AppContext->>AppContext: 初始化 Auth/RateLimiter\\n    CLI->>Server: 启动 APIServer:8765\\n    CLI->>Server: 启动 HealthServer:8766\\n    CLI->>Server: 启动 DashboardServer:8767\\n    Server-->>User: 服务已启动\\n```\\n\\n## 仪表盘\\n\\nMemoryMesh 提供基于 FastAPI + HTMX 的 Web 仪表盘。\\n\\n### 访问地址\\n\\n| 服务 | 默认端口 | 说明 |\\n|------|----------|------|\\n| API 服务器 | 8765 | MCP 工具和 REST API |\\n| 健康检查 | 8766 | 健康状态端点 |\\n| Web 仪表盘 | 8767 | 可视化界面 |\\n\\n### 仪表盘功能\\n\\n- **数据源概览**：显示已配置的数据源状态\\n- **搜索界面**：执行语义和关键词混合搜索\\n- **记忆层级**：展示热/温/冷数据块分布\\n- **实体列表**：展示提取的命名实体\\n- **时间线**：查看情景记忆事件\\n- **图谱视图**：可视化知识图谱\\n\\n资料来源：[src/memorymesh/server/dashboard.py:1-200]()\\n\\n## Ollama 集成\\n\\n### 安装 Ollama\\n\\n```bash\\n# macOS/Linux\\ncurl -fsSL https://ollama.com/install.sh | sh\\n\\n# Windows - 从 https://ollama.com/download 下载\\n```\\n\\n### 启动 Ollama\\n\\n```bash\\n# 启动 Ollama 服务\\nollama serve\\n\\n# 下载模型\\nollama pull llama3.2\\n```\\n\\n### 配置 MemoryMesh 使用 Ollama\\n\\n```yaml\\nollama:\\n  enabled: true\\n  base_url: http://localhost:11434\\n  model: llama3.2\\n\\nmemory:\\n  entity_extraction:\\n    enabled: true\\n```\\n\\n## 记忆分层\\n\\nMemoryMesh 实现三层记忆模型，自动管理数据访问频率：\\n\\n| 层级 | 名称 | 保留时间 | 说明 |\\n|------|------|----------|------|\\n| 热数据 | Hot | 7 天 | 高频访问，保持在内存中 |\\n| 温数据 | Warm | 30 天 | 中频访问，定期检查 |\\n| 冷数据 | Cold | 90 天+ | 低频访问，触发遗忘机制 |\\n\\n```yaml\\nmemory:\\n  tiers:\\n    hot_days: 7\\n    warm_days: 30\\n    cold_days: 90\\n  forgetting:\\n    enabled: true\\n    cold_to_archive_after_days: 180\\n```\\n\\n## 故障排除\\n\\n### 常见问题\\n\\n**Q: 配置文件加载失败**\\n\\n```bash\\n# 检查配置文件路径\\nmemorymesh status --verbose\\n\\n# 指定配置文件\\nmemorymesh start --config /path/to/config.yaml\\n```\\n\\n**Q: 向量化模型下载失败**\\n\\n```bash\\n# 设置本地文件优先\\n# 在代码中设置 SentenceTransformersProvider(local_files_only=True)\\n```\\n\\n**Q: Ollama 连接失败**\\n\\n```bash\\n# 确认 Ollama 正在运行\\nollama list\\n\\n# 测试连接\\ncurl http://localhost:11434/api/tags\\n```\\n\\n**Q: 数据库锁定**\\n\\n```bash\\n# 清理锁文件\\nrm ~/.memorymesh/*.lock\\n```\\n\\n## 下一步\\n\\n- 查看 [配置参考](config-reference) 了解完整配置选项\\n- 查看 [API 文档](api) 了解 MCP 工具\\n- 查看 [开发指南](development) 了解如何贡献代码\\n- 查看 [CHANGELOG](CHANGELOG) 了解版本更新\\n\\n资料来源：[CHANGELOG.md:1-100]()\\n\"\n}\n\n---\n\n<a id='page-architecture'></a>\n\n## 系统架构\n\n### 相关页面\n\n相关主题：[MemoryMesh 简介](#page-introduction), [索引管道](#page-indexing-pipeline), [搜索引擎](#page-search-engine)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [ARCHITECTURE.md](https://github.com/kilhubprojects/memory-mesh/blob/main/ARCHITECTURE.md)\n- [src/memorymesh/server/app.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/app.py)\n- [src/memorymesh/server/transports.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/transports.py)\n- [src/memorymesh/indexer/file_indexer.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/indexer/file_indexer.py)\n- [src/memorymesh/parsing/obsidian_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/obsidian_parser.py)\n- [src/memorymesh/connectors/logseq_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\n- [src/memorymesh/storage/file_repository.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/storage/file_repository.py)\n</details>\n\n# 系统架构\n\nMemoryMesh 是一个本地优先的个人知识图谱与记忆管理系统，旨在将分散在各类笔记工具（Obsidian、Logseq、Roam、Notion 等）中的内容统一索引、检索与关联。本页面详细说明其核心系统架构、各模块职责及数据流转路径。\n\n## 整体架构概览\n\nMemoryMesh 采用分层架构，核心组件包括**数据源连接层**、**解析与分块层**、**存储与索引层**、**检索与推理层**，以及**服务与接口层**。各层职责清晰，依赖关系如下：\n\n```mermaid\ngraph TD\n    subgraph 数据源层\n        OBS[Obsidian Vault]\n        LOG[Logseq Graph]\n        ROAM[Roam Research]\n        NOTION[Notion Export]\n        CONFL[Confluence]\n        EMAIL[Email .mbox]\n        CAL[Calendar .ics]\n    end\n\n    subgraph 连接器层\n        OBS_C[ObsidianConnector]\n        LOG_C[LogseqConnector]\n        ROAM_C[RoamConnector]\n        NOTION_C[NotionParser]\n        CONFL_C[ConfluenceConnector]\n    end\n\n    subgraph 解析层\n        MARKDOWN[MarkdownParser]\n        OBS_P[ObsidianParser]\n        HTML_P[NotionHTMLParser]\n    end\n\n    subgraph 分块层\n        MD_CHUNK[MarkdownChunker]\n        REC_CHUNK[RecursiveChunker]\n    end\n\n    subgraph 存储层\n        SQLite[(SQLite 元数据库)]\n        QDRANT[(Qdrant 向量库)]\n        CHROMS[Chroma 向量库]\n    end\n\n    subgraph 索引层\n        IDX[FileIndexer]\n        EMB[EmbeddingProvider]\n    end\n\n    subgraph 服务层\n        API[FastAPI MCP Server]\n        DASH[Dashboard Server]\n        HEALTH[Health Server]\n        MCP[MCP Tools]\n    end\n\n    OBS --> OBS_C\n    LOG --> LOG_C\n    ROAM --> ROAM_C\n    NOTION --> NOTION_C\n    CONFL --> CONFL_C\n\n    OBS_C --> OBS_P\n    LOG_C --> MARKDOWN\n    ROAM_C --> MARKDOWN\n    NOTION_C --> HTML_P\n\n    OBS_P --> MD_CHUNK\n    HTML_P --> MD_CHUNK\n    MARKDOWN --> REC_CHUNK\n\n    MD_CHUNK --> IDX\n    REC_CHUNK --> IDX\n    IDX --> EMB\n    EMB --> QDRANT\n    EMB --> CHROMS\n    IDX --> SQLite\n\n    SQLite --> API\n    QDRANT --> API\n    CHROMS --> API\n    API --> MCP\n    API --> DASH\n    API --> HEALTH\n```\n\n**资料来源**：[ARCHITECTURE.md](https://github.com/kilhubprojects/memory-mesh/blob/main/ARCHITECTURE.md)\n\n## 核心组件\n\n### 1. 连接器层（Connectors）\n\n连接器负责从各类外部数据源批量读取文档，统一输出为 `ParsedDocument` 对象。各连接器支持的平台如下：\n\n| 连接器 | 配置类 | 数据格式 | 特性 |\n|--------|--------|----------|------|\n| `ObsidianConnector` | `ObsidianSourceConfig` | Markdown | 解析 YAML frontmatter、`[[wikilinks]]` |\n| `LogseqConnector` | `LogseqConfig` | Markdown | 处理 `((uuid))` 块引用、`{{embed}}` 嵌入、`key:: value` 属性 |\n| `RoamConnector` | `RoamConfig` | JSON | 递归展平嵌套块、清除 `{{[[...]]}}` 模板语法 |\n| `NotionParser` | `NotionSourceConfig` | HTML 导出 | 使用标准库 `html.parser` 解析 |\n| `ConfluenceConnector` | `ConfluenceConfig` | REST API | HTTP Basic 认证、分页拉取 |\n| `EmailParser` | `EmailSourceConfig` | .mbox | 偏好 `text/plain`，回退到 stripped HTML |\n| `CalendarParser` | `CalendarSourceConfig` | .ics | 提取 VEVENT 摘要、时间、地点 |\n\n**资料来源**：[src/memorymesh/connectors/logseq_connector.py:1-80](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\n\n### 2. 解析层（Parsers）\n\n解析器将原始文件内容转换为结构化的 `ParsedDocument`，提取纯文本与元数据。\n\n#### Obsidian 解析器\n\n`ObsidianParser` 专门处理 Obsidian 格式的 Markdown 文件：\n\n- **YAML frontmatter 提取**：匹配 `---` 分隔符之间的内容，解析 `tags`、`aliases`、`created`、`modified` 字段\n- **Wikilink 提取**：正则 `_WIKILINK_RE = r\"(?<!!)\\[\\[([^\\[\\]|#]+?)(?:\\|[^\\[\\]]*?)?\\]\\]\"` 捕获双向链接目标\n- **过滤嵌入图片**：`![[img]]` 格式被排除在 backlinks 之外\n\n```python\n_WIKILINK_RE = re.compile(r\"(?<!!)\\[\\[([^\\[\\]|#]+?)(?:\\|[^\\[\\]]*?)?\\]\\]\")\n```\n\n**资料来源**：[src/memorymesh/parsing/obsidian_parser.py:20-30](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/obsidian_parser.py)\n\n#### Logseq 解析器\n\n`LogseqConnector` 内置解析逻辑，处理 Logseq 特有语法：\n\n| 语法模式 | 正则 | 转换结果 |\n|----------|------|----------|\n| 块引用 | `\\(\\([0-9a-f-]{36}\\)\\)` | `[block]` |\n| 嵌入 | `\\{\\{embed \\[\\[([^\\]]+)\\]\\]\\}\\}` | `[embed: Page]` |\n| 查询块 | `\\{\\{query[^}]*\\}\\}` | 整块移除 |\n| 属性行 | `^([\\w-]+)::\\s*(.+)$` | 存入 metadata |\n\n**资料来源**：[src/memorymesh/connectors/logseq_connector.py:40-50](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\n\n### 3. 分块层（Chunking）\n\n分块策略决定了向量检索的粒度。MemoryMesh 支持以下分块器：\n\n| 分块器 | 策略 | 配置参数 |\n|--------|------|----------|\n| `RecursiveChunker` | 递归字符拆分 | `chunk_size=800`, `chunk_overlap=50` |\n| `MarkdownChunker` | 按 ATX 标题（`#`, `##` 等）切分 | `max_chunk_size=800` |\n\n`MarkdownChunker` 首先按标题分割文档，超出 `max_chunk_size` 的节交给 `RecursiveChunker` 进一步拆分，并保留 `heading_path` 元数据用于精确定位。\n\n**资料来源**：[src/memorymesh/chunking/markdown.py:1-50](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/markdown.py)\n\n### 4. 存储层（Storage）\n\n#### 元数据存储（SQLite）\n\n`FileRepository` 负责管理 SQLite 数据库中的以下表：\n\n- `files`：文件记录，包含路径、SHA-256、修改时间、块数、索引状态等\n- `sources`：数据源配置\n- `index_state`：索引状态追踪\n\n文件记录使用 `ON CONFLICT(path) DO UPDATE` 实现 upsert 语义，保证幂等性：\n\n```sql\nINSERT INTO files\n    (path, source_name, sha256, mtime, size_bytes, file_type,\n     n_chunks, status, error_message, indexed_at, embedding_model_id)\nVALUES (...)\nON CONFLICT(path) DO UPDATE SET\n    source_name = excluded.source_name,\n    sha256 = excluded.sha256,\n    ...\n```\n\n**资料来源**：[src/memorymesh/storage/file_repository.py:15-35](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/storage/file_repository.py)\n\n#### 向量存储\n\nMemoryMesh 支持多种向量数据库作为后端：\n\n| 向量库 | 配置键 | 说明 |\n|--------|--------|------|\n| Qdrant | `vector_store.type: qdrant` | 高性能向量检索 |\n| Chroma | `vector_store.type: chroma` | 轻量级本地向量库 |\n\n向量由 `EmbeddingProvider` 生成，支持 Ollama 本地模型推理。\n\n### 5. 索引层（Indexer）\n\n`FileIndexer` 是索引流程的核心编排器，其主要职责：\n\n```mermaid\ngraph LR\n    A[文件路径] --> B{文件类型判断}\n    B -->|Markdown| C[MarkdownChunker]\n    B -->|其他| D[TextParser]\n    C --> E[RecursiveChunker]\n    D --> E\n    E --> F[EmbeddingProvider]\n    F --> G[向量写入 Qdrant/Chroma]\n    E --> H[Chunk 列表]\n    H --> I[FileRepository upsert]\n```\n\n索引过程中：\n1. 根据文件扩展名选择对应 Parser\n2. Parser 输出 `ParsedDocument`（含纯文本与元数据）\n3. Chunker 将文档切分为 `Chunk` 列表\n4. `EmbeddingProvider` 为每个 chunk 生成向量\n5. 向量写入向量库，元数据写入 SQLite\n\n**资料来源**：[src/memorymesh/indexer/file_indexer.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/indexer/file_indexer.py)\n\n### 6. 服务层（Server）\n\n#### MCP Server\n\nMemoryMesh 通过 FastMCP 暴露 MCP（Model Context Protocol）工具，提供以下能力：\n\n| MCP 工具 | 功能描述 |\n|----------|----------|\n| `search_memory` | 混合检索：向量相似度 + 关键词 |\n| `ask_memory` | RAG 问答：检索 → 上下文组装 → Ollama 生成 |\n| `pin_memory` | 将 chunk 钉住防止遗忘衰减 |\n| `forget_memory` | 抑制或冷却指定 chunk |\n| `get_memory_tier` | 查询 chunk 所在记忆层级 |\n\n所有工具均通过 `auth_guard.py` 中的 `check_access()` 进行权限校验。\n\n**资料来源**：[src/memorymesh/server/tools/forget_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/forget_memory.py)\n\n#### Dashboard Server\n\n基于 FastAPI + HTMX 的 Web 界面，运行在 `:8767` 端口：\n\n| 路由 | 功能 |\n|------|------|\n| `/` | 数据源概览 |\n| `/search` | 检索界面 |\n| `/tiers` | 记忆层级分布统计 |\n| `/entities` | 提取的实体列表 |\n| `/timeline` | 情景记忆时间线 |\n| `/graph-ui` | 知识图谱可视化 |\n\n**资料来源**：[src/memorymesh/server/dashboard.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/dashboard.py)\n\n#### Health Server\n\n轻量级健康检查端点，运行在 `:8766` 端口，用于进程监控与外部探测。\n\n## 关键数据模型\n\n### ParsedDocument\n\n```python\nclass ParsedDocument(BaseModel):\n    path: Path\n    text: str\n    file_type: str\n    encoding: str = \"utf-8\"\n    metadata: dict[str, object] = Field(default_factory=dict)\n```\n\n### Chunk\n\n```python\nclass Chunk(BaseModel):\n    path: Path\n    chunk_index: int\n    text: str\n    start_char: int\n    end_char: int\n    file_type: str = \"\"\n    metadata: ChunkMetadata = Field(default_factory=ChunkMetadata)\n```\n\n**资料来源**：[src/memorymesh/core/models/chunk.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/chunk.py)\n\n## 配置架构\n\nMemoryMesh 使用 YAML 配置文件管理所有组件行为，主要配置节点：\n\n```yaml\nsources:                    # 数据源列表\n  - type: obsidian\n    path: ~/Vault\n  - type: logseq\n    vault_path: ~/Logseq/my-graph\n\nvector_store:\n  type: qdrant              # 或 chroma\n  path: ~/.memorymesh/qdrant\n\nmemory:\n  tiers:\n    enabled: true\n    strategy: importance_based\n  forgetting:\n    enabled: true\n    decay_rate: 0.95\n  episodic:\n    enabled: true\n\nentity_extraction:\n  enabled: true\n  ollama_url: http://localhost:11434\n\nauth:\n  enabled: false            # 默认关闭\n```\n\n## 记忆层级系统\n\nMemoryMesh 引入了基于重要性的记忆层级管理：\n\n```mermaid\ngraph TD\n    HOT[热记忆 Hot] --> WARM[温记忆 Warm]\n    WARM --> COLD[冷记忆 Cold]\n    COLD --> ARCHIVE[归档 Archive]\n\n    style HOT fill:#ff6b6b\n    style WARM fill:#feca57\n    style COLD fill:#54a0ff\n    style ARCHIVE fill:#576574\n```\n\n| 层级 | 用途 | 衰减策略 |\n|------|------|----------|\n| Hot | 高频访问、钉住内容 | 不衰减 |\n| Warm | 最近访问 | 轻量衰减 |\n| Cold | 长期未访问 | 快速衰减 |\n| Archive | 极低相关性 | 可选自动清理 |\n\n`TieredMemoryManager` 根据访问频率与用户显式操作动态调整 chunk 所在层级。\n\n## 认证与权限\n\n`auth_guard.py` 提供统一的权限检查接口：\n\n```python\ncheck_access(ctx: AppContext, action: str, source: str | None) -> bool\n```\n\n支持的权限操作：\n- `read_source`：读取指定数据源\n- `write_source`：修改指定数据源\n- `admin`：管理功能\n\n当 `auth.enabled: false`（默认值）时，所有权限检查自动放行。\n\n## 工作流程总览\n\n```mermaid\nsequenceDiagram\n    participant CLI as CLI (start)\n    participant CTX as AppContext\n    participant CONN as Connectors\n    participant IDX as FileIndexer\n    participant EMB as EmbeddingProvider\n    participant VDB as Vector Store\n    participant SQL as SQLite\n\n    CLI->>CTX: 初始化配置\n    CTX->>CONN: 创建连接器实例\n    loop 每次索引周期\n        CONN->>CONN: fetch_documents()\n        CONN-->>IDX: ParsedDocument stream\n        loop 每个文档\n            IDX->>IDX: parse() → ParsedDocument\n            IDX->>IDX: chunk() → Chunk list\n            IDX->>EMB: embed(chunks)\n            EMB-->>IDX: ChunkWithEmbedding list\n            IDX->>VDB: upsert(embeddings)\n            IDX->>SQL: upsert(FileRecord)\n        end\n    end\n    CLI->>CTX: 启动 MCP Server\n    CTX->>CTX: 注册 MCP 工具\n    Note over CTX: Dashboard :8767, Health :8766\n```\n\n## 扩展机制\n\nMemoryMesh 设计支持以下扩展点：\n\n1. **自定义 Parser**：继承 `Parser` 基类，注册到 `source.type` 映射\n2. **自定义 ChunkStrategy**：实现 `Chunker` 接口\n3. **自定义 VectorStore**：实现 `VectorStore` 接口，适配新的向量数据库\n4. **自定义 Connector**：实现 `Connector` 接口，从新平台拉取数据\n\n## 技术栈总结\n\n| 层级 | 技术选型 |\n|------|----------|\n| 核心框架 | Python 3.11+, Pydantic |\n| Web 框架 | FastAPI, Starlette |\n| 界面 | HTMX, 原生 HTML/CSS |\n| 向量库 | Qdrant / Chroma |\n| 元数据 | SQLite |\n| 本地推理 | Ollama |\n| 协议 | MCP (FastMCP) |\n| 日志 | Loguru |\n| 配置 | YAML + Pydantic ConfigDict |\n\n所有数据默认存储在 `~/.memorymesh/` 目录下，保持完全的本地化与隐私保护。\n\n---\n\n<a id='page-indexing-pipeline'></a>\n\n## 索引管道\n\n### 相关页面\n\n相关主题：[系统架构](#page-architecture), [文件解析器](#page-parsers), [文本分块策略](#page-chunkers), [搜索引擎](#page-search-engine)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/indexer/file_indexer.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/indexer/file_indexer.py)\n- [src/memorymesh/indexer/watcher.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/indexer/watcher.py)\n- [src/memorymesh/parsing/registry.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/registry.py)\n- [src/memorymesh/embeddings/registry.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/embeddings/registry.py)\n- [src/memorymesh/storage/vector_store.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/storage/vector_store.py)\n- [src/memorymesh/storage/bm25_index.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/storage/bm25_index.py)\n</details>\n\n# 索引管道\n\n索引管道是 MemoryMesh 的核心子系统，负责将各种来源的文档转换为可搜索的向量和全文索引数据。本页面详细介绍索引管道的架构设计、数据流、核心组件及其交互方式。\n\n## 架构概述\n\n索引管道采用模块化设计，主要包含以下处理阶段：\n\n```mermaid\ngraph TD\n    A[文档源] --> B[解析器 Registry]\n    B --> C[解析器 Parser]\n    C --> D[ParsedDocument]\n    D --> E[分块器 Chunker]\n    E --> F[Chunk 列表]\n    F --> G[嵌入向量生成]\n    G --> H[向量存储]\n    G --> I[BM25 索引]\n    H --> J[元数据存储]\n    I --> J\n```\n\n管道支持多种文档格式，包括本地 Markdown、Obsidian 笔记、Notion 导出、Roam Research、Logseq、Confluence 以及 Email 和日历等。资料来源：[src/memorymesh/parsing/obsidian_parser.py]()、[src/memorymesh/parsing/notion_parser.py]()、[src/memorymesh/connectors/logseq_connector.py]()、[src/memorymesh/connectors/roam_connector.py]()、[src/memorymesh/connectors/confluence_connector.py]()\n\n## 核心处理流程\n\n### 1. 文档解析阶段\n\n解析器注册表 (`ParserRegistry`) 根据文件类型和来源配置选择合适的解析器。每种解析器负责将特定格式的文档转换为统一的 `ParsedDocument` 数据结构。\n\n支持的解析器类型：\n\n| 解析器 | 文件类型 | 特殊功能 |\n|--------|----------|----------|\n| MarkdownParser | .md, .mdx, .markdown | 基础解析 |\n| ObsidianParser | .md | YAML frontmatter 提取、wikilink 解析 |\n| NotionParser | .html, .htm | Notion 导出格式处理 |\n| LogseqConnector | .md | 属性行解析、block 引用处理 |\n| RoamConnector | JSON | 递归 block 扁平化 |\n| ConfluenceConnector | API | HTML 内容提取 |\n\n资料来源：[src/memorymesh/parsing/registry.py]()\n\n`ParsedDocument` 模型包含以下关键字段：\n\n```python\npath: Path\ntext: str\nfile_type: str\nencoding: str\nmetadata: dict[str, object]  # 包含 frontmatter、tags、aliases 等\n```\n\n资料来源：[src/memorymesh/core/models/chunk.py]()\n\n### 2. 文本分块阶段\n\n分块器将长文档拆分为适合嵌入的段落。每个 `Chunk` 对象包含文本内容、字符位置信息和元数据。\n\n| 分块器 | 适用场景 | 分块策略 |\n|--------|----------|----------|\n| MarkdownChunker | Markdown 文档 | 按 ATX 标题层级切分 |\n| CodeChunker | 源代码文件 | 按函数/类定义节点切分 |\n| RecursiveChunker | 通用文本 | 递归字符级切分 |\n\nMarkdownChunker 特别维护 `heading_path` 元数据字段，记录文档中的完整标题路径，便于精确定位搜索结果。资料来源：[src/memorymesh/chunking/markdown.py]()\n\nCodeChunker 使用 AST 解析提取函数名、类名和语言类型，为代码搜索提供语义级支持。资料来源：[src/memorymesh/chunking/code.py]()\n\n### 3. 向量嵌入阶段\n\n嵌入向量生成器将文本块转换为高维向量表示，用于语义相似度搜索。嵌入提供者通过注册表统一管理，支持配置不同的嵌入模型。\n\n```mermaid\nsequenceDiagram\n    participant C as Chunk\n    participant E as EmbeddingProvider\n    participant V as VectorStore\n    participant M as MetadataStore\n    \n    C->>E: 批量生成嵌入向量\n    E-->>C: embedding: list[float]\n    C->>V: 存储向量 + 元数据\n    C->>M: 创建 FileRecord\n```\n\n资料来源：[src/memorymesh/indexer/file_indexer.py]()\n\n### 4. 混合索引阶段\n\nMemoryMesh 采用混合搜索策略，同时维护向量索引和 BM25 全文索引。\n\n| 索引类型 | 用途 | 存储位置 |\n|----------|------|----------|\n| 向量索引 | 语义相似度搜索 | VectorStore |\n| BM25 索引 | 关键词精确匹配 | BM25Index |\n\nBM25 索引器构建倒排索引，支持按词频和文档频率计算相关性评分。资料来源：[src/memorymesh/storage/bm25_index.py]()\n\n向量存储使用配置的向量数据库，支持多种后端实现。资料来源：[src/memorymesh/storage/vector_store.py]()\n\n## FileIndexer 核心组件\n\n`FileIndexer` 是索引管道的核心编排器，协调各子系统的协作。\n\n### 主要方法\n\n| 方法 | 职责 |\n|------|------|\n| `index_file(path)` | 单文件索引入口 |\n| `index_directory(root, ...)` | 目录批量索引 |\n| `process_document(doc, path, source_name)` | 文档处理流水线 |\n\n资料来源：[src/memorymesh/indexer/file_indexer.py]()\n\n### 索引结果记录\n\n索引完成后，系统创建 `FileRecord` 记录文件状态：\n\n```python\nFileRecord(\n    path=str(path),\n    source_name=source_name,\n    sha256=current_hash,        # 文件内容哈希\n    mtime=stat.st_mtime,        # 修改时间\n    size_bytes=stat.st_size,    # 文件大小\n    file_type=ext,              # 文件类型\n    n_chunks=len(chunks),       # 分块数量\n    status=\"indexed\",           # 索引状态\n    indexed_at=time.time(),     # 索引时间戳\n    embedding_model_id=model_id # 嵌入模型标识\n)\n```\n\n资料来源：[src/memorymesh/indexer/file_indexer.py]()、[src/memorymesh/core/models/chunk.py]()\n\n### 增量索引机制\n\n系统通过 SHA-256 哈希和 mtime 比对检测文件变化，仅对变更文件重新索引：\n\n```python\ncurrent_hash = hashlib.sha256(content).hexdigest()\nif current_hash != existing_file.sha256:\n    # 重新索引\n```\n\n资料来源：[src/memorymesh/indexer/file_indexer.py]()\n\n## 监视器组件\n\n`FileWatcher` 组件监听文件系统变化，触发增量索引。\n\n```mermaid\ngraph LR\n    A[文件系统事件] --> B{事件类型}\n    B -->|创建/修改| C[触发索引]\n    B -->|删除| D[标记文件已删除]\n    B -->|重命名| E[更新文件路径]\n```\n\n资料来源：[src/memorymesh/indexer/watcher.py]()\n\n| 功能 | 说明 |\n|------|------|\n| 增量更新 | 仅索引变更文件 |\n| 软删除处理 | 标记而非立即删除 |\n| 防抖机制 | 避免频繁触发 |\n\n## 配置选项\n\n### IndexingConfig 主要字段\n\n| 字段 | 类型 | 默认值 | 说明 |\n|------|------|--------|------|\n| `chunk_size` | int | 800 | 分块目标字符数 |\n| `chunk_overlap` | int | 50 | 分块重叠字符数 |\n| `generate_summaries` | bool | False | 是否生成摘要块 |\n| `extract_entities` | bool | True | 是否提取实体 |\n\n### EmbeddingConfig 主要字段\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `provider` | str | 嵌入提供者名称 |\n| `model_id` | str | 模型标识符 |\n| `batch_size` | int | 批处理大小 |\n| `dimensions` | int | 向量维度 |\n\n资料来源：[src/memorymesh/embeddings/registry.py]()\n\n## 错误处理\n\n索引管道内置完善的错误处理机制：\n\n| 错误类型 | 处理策略 | 状态记录 |\n|----------|----------|----------|\n| 解析错误 | 返回错误文档，记录到 metadata | `parse_error` |\n| 编码错误 | 使用 fallback 编码或跳过 | `parse_error` |\n| 嵌入失败 | 使用 fallback 提供者 | `index_error` |\n| 存储错误 | 回滚事务，记录错误信息 | `index_error` |\n\n`FileRecord` 的 `status` 字段可能值：`indexed`、`parse_error`、`unsupported`、`deleted`、`pending_reindex`。资料来源：[src/memorymesh/core/models/chunk.py]()\n\n## 数据流总结\n\n```\nSource File → Parser → ParsedDocument → Chunker → Chunks\n                                                      ↓\n                                    ┌─────────────────┴─────────────────┐\n                                    ↓                                   ↓\n                            EmbeddingProvider                  BM25Indexer\n                                    ↓                                   ↓\n                              VectorStore                         BM25Index\n                                    └─────────────────┬─────────────────┘\n                                                      ↓\n                                              MetadataStore\n                                              (FileRecord)\n```\n\n索引管道通过模块化设计实现了灵活的文档处理能力，支持多种数据源的统一索引，并提供向量和全文双重搜索能力，满足不同场景的检索需求。\n\n---\n\n<a id='page-parsers'></a>\n\n## 文件解析器\n\n### 相关页面\n\n相关主题：[索引管道](#page-indexing-pipeline), [文本分块策略](#page-chunkers)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/parsing/base.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/base.py)\n- [src/memorymesh/parsing/markdown.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/markdown.py)\n- [src/memorymesh/parsing/obsidian_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/obsidian_parser.py)\n- [src/memorymesh/parsing/notion_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/notion_parser.py)\n</details>\n\n# 文件解析器\n\n## 概述\n\n文件解析器（Parser）是 MemoryMesh 索引管道中的第一环，负责将各种来源的原始文件转换为统一的 `ParsedDocument` 数据结构。每个解析器专注于特定的文件格式或数据源，提取文本内容和元数据，为后续的分块（Chunking）和向量化（Embedding）做准备。\n\n解析器采用**策略模式**，通过文件扩展名和源类型自动选择合适的解析器实现。系统内置了针对 Markdown、Obsidian、Notion、PDF、DOCX、Email 等格式的专业解析器，同时也支持通过扩展机制接入新的数据源。\n\n资料来源：[src/memorymesh/parsing/base.py]()\n\n## 架构设计\n\n### 解析器基类\n\n所有解析器都继承自 `Parser` 基类，定义统一接口：\n\n```python\nclass Parser(ABC):\n    @property\n    @abstractmethod\n    def supported_extensions(self) -> frozenset[str]:\n        \"\"\"返回解析器支持的文件扩展名集合\"\"\"\n        ...\n\n    @abstractmethod\n    def parse(self, path: Path) -> ParsedDocument:\n        \"\"\"解析指定路径的文件，返回 ParsedDocument\"\"\"\n        ...\n```\n\n资料来源：[src/memorymesh/parsing/base.py]()\n\n### 解析流程\n\n```mermaid\ngraph TD\n    A[原始文件] --> B{文件类型检测}\n    B -->|Markdown .md| C[MarkdownParser]\n    B -->|Obsidian .md| D[ObsidianParser]\n    B -->|Notion .html| E[NotionParser]\n    B -->|PDF .pdf| F[PDFParser]\n    B -->|DOCX .docx| G[DOCXParser]\n    B -->|Email .eml/.msg| H[EmailParser]\n    C --> I[ParsedDocument]\n    D --> I\n    E --> I\n    F --> I\n    G --> I\n    H --> I\n```\n\n### ParsedDocument 数据模型\n\n解析结果封装在 `ParsedDocument` 模型中：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `path` | `Path` | 文件绝对路径 |\n| `text` | `str` | 提取的纯文本内容 |\n| `file_type` | `str` | 规范化文件类型标识 |\n| `encoding` | `str` | 源文件编码 |\n| `metadata` | `dict` | 格式特定的元数据 |\n\n资料来源：[src/memorymesh/core/models/__init__.py]()\n\n## 内置解析器\n\n### Markdown 解析器\n\n**文件路径**: `src/memorymesh/parsing/markdown.py`\n\n`MarkdownParser` 是标准 Markdown 文件的解析器，使用与文本解析器相同的编码容错读取机制。它将解析结果标记为 `file_type=\".md\"`，使后续分块层能够选择标题感知的分割器。\n\n```python\nclass MarkdownParser(Parser):\n    @property\n    def supported_extensions(self) -> frozenset[str]:\n        return frozenset({\".md\", \".mdx\", \".markdown\"})\n\n    def parse(self, path: Path) -> ParsedDocument:\n        text, encoding, error = _read_with_fallback(path)\n        meta: dict[str, object] = {}\n        if error:\n            meta[\"error\"] = error\n        return ParsedDocument(\n            path=path,\n            text=text,\n            file_type=\".md\",\n            encoding=encoding,\n            metadata=meta,\n        )\n```\n\n资料来源：[src/memorymesh/parsing/markdown.py]()\n\n### Obsidian 解析器\n\n**文件路径**: `src/memorymesh/parsing/obsidian_parser.py`\n\n`ObsidianParser` 继承自 `MarkdownParser`，增加了对 Obsidian 特有语法的支持：\n\n| 功能 | 说明 |\n|------|------|\n| YAML 前置元数据 | 提取 `---` 分隔符之间的内容 |\n| Wikilink 反向链接 | 识别 `[[链接]]` 和 `[[链接\\|别名]]` 模式 |\n| 嵌入图片过滤 | 排除 `![[图片]]` 等嵌入媒体 |\n| 标签提取 | 解析 `tags:` 字段和内联 `#标签` 语法 |\n\n```python\n# YAML 前置元数据正则\n_FRONTMATTER_RE = re.compile(\n    r\"^---\\r?\\n(.*?)\\r?\\n(?:---|\\.\\.\\.)(?:\\r?\\n|$)\",\n    re.DOTALL,\n)\n\n# Wikilink 提取正则（排除 ![[ 嵌入]]）\n_WIKILINK_RE = re.compile(r\"(?<!!)\\[\\[([^\\[\\]|#]+?)(?:\\|[^\\[\\]]*?)?\\]\\]\")\n```\n\n提取的元数据字段：\n\n```python\nmeta[\"frontmatter\"] = fm_data          # YAML 字段字典\nmeta[\"tags\"] = tags                     # 标签列表\nmeta[\"aliases\"] = aliases               # 别名列表\nmeta[\"created\"] = created              # 创建时间\nmeta[\"modified\"] = modified             # 修改时间\nmeta[\"backlinks\"] = wikilink_targets    # Wikilink 目标列表\n```\n\n资料来源：[src/memorymesh/parsing/obsidian_parser.py]()\n\n### Notion 解析器\n\n**文件路径**: `src/memorymesh/parsing/notion_parser.py`\n\n`NotionParser` 专门处理 Notion HTML 导出格式，仅依赖标准库 `html.parser`，无需外部依赖。\n\n```python\nclass _NotionHTMLParser(HTMLParser):\n    \"\"\"SAX 风格解析器，收集纯文本和元数据\"\"\"\n    \n    _SKIP_TAGS: frozenset[str] = frozenset(\n        {\"style\", \"script\", \"head\", \"meta\", \"link\"}\n    )\n```\n\n解析能力：\n\n- 提取 `<title>` 标签内容\n- 提取 `<h1>` 可见页面标题\n- 收集 `data-type` 属性值（数据库属性类型）\n- 剥离所有 HTML 标签获取纯文本\n- 从文件名提取 Notion 页面 UUID\n\n```python\n_UUID_FILENAME_RE = re.compile(\n    r\"([0-9a-f]{8}(?:[0-9a-f]{4}){3}[0-9a-f]{12})(?:\\s|\\.|$)\",\n    re.IGNORECASE,\n)\n```\n\nNotion 解析器返回的元数据包含：\n\n| 字段 | 说明 |\n|------|------|\n| `notion_id` | 页面 UUID |\n| `database_name` | 所属数据库名称 |\n| `title` | 页面标题 |\n| `db_properties` | 数据库属性列表 |\n\n资料来源：[src/memorymesh/parsing/notion_parser.py]()\n\n## 支持的文件格式\n\n| 解析器 | 扩展名 | 源类型 |\n|--------|--------|--------|\n| `MarkdownParser` | `.md`, `.mdx`, `.markdown` | 通用 Markdown |\n| `ObsidianParser` | `.md` | `obsidian` |\n| `NotionParser` | `.html`, `.htm` | `notion` |\n| `PDFParser` | `.pdf` | 通用 |\n| `DOCXParser` | `.docx` | 通用 |\n| `EmailParser` | `.eml`, `.msg` | 通用 |\n\n## 解析模式\n\n### 编码容错读取\n\n解析器使用 `_read_with_fallback` 函数处理各种文件编码：\n\n```python\ndef _read_with_fallback(path: Path) -> tuple[str, str, str | None]:\n    \"\"\"尝试 UTF-8 读取，失败时回退到 latin-1\"\"\"\n```\n\n该函数按顺序尝试：\n1. UTF-8 编码\n2. 回退到 `latin-1` 编码\n3. 返回错误信息而非抛出异常\n\n资料来源：[src/memorymesh/parsing/text.py]()\n\n### 错误处理\n\n所有解析器遵循统一的错误处理策略：\n\n```python\nif error:\n    meta[\"error\"] = error\n    return ParsedDocument(\n        path=path,\n        text=\"\",\n        file_type=file_type,\n        encoding=encoding,\n        metadata=meta,\n    )\n```\n\n解析失败时返回空的 `text` 内容，但保留 `error` 字段供诊断使用。\n\n## 与连接器的协作\n\n解析器不仅处理本地文件，还被**连接器（Connector）**模块间接调用：\n\n```mermaid\ngraph LR\n    A[连接器] -->|fetch_documents| B[ParsedDocument]\n    B --> C[索引器]\n    C --> D[分块]\n    D --> E[向量化]\n    E --> F[向量数据库]\n```\n\n连接器处理远程数据获取和格式转换，然后使用解析器或解析后的格式输出 `ParsedDocument`：\n\n- **RoamConnector** - 解析 Roam Research JSON 导出\n- **LogseqConnector** - 处理 Logseq Markdown 文件\n- **NotionConnector** - 调用 Notion API 获取页面\n- **ConfluenceConnector** - 从 Confluence REST API 获取页面\n\n资料来源：[src/memorymesh/connectors/roam_connector.py]()\n资料来源：[src/memorymesh/connectors/logseq_connector.py]()\n资料来源：[src/memorymesh/connectors/notion_connector.py]()\n资料来源：[src/memorymesh/connectors/confluence_connector.py]()\n\n## 使用示例\n\n### 直接使用解析器\n\n```python\nfrom pathlib import Path\nfrom memorymesh.parsing.obsidian_parser import ObsidianParser\n\nparser = ObsidianParser()\ndoc = parser.parse(Path(\"/vault/my-note.md\"))\n\nprint(f\"文本长度: {len(doc.text)}\")\nprint(f\"标签: {doc.metadata.get('tags')}\")\nprint(f\"反向链接: {doc.metadata.get('backlinks')}\")\n```\n\n### 配置源类型自动选择\n\n当 `source.type` 配置为 `obsidian` 时，系统自动注册 `ObsidianParser` 处理 `.md` 文件；通用 Markdown 源则使用标准 `MarkdownParser`。\n\n## 扩展新的解析器\n\n实现自定义解析器需继承 `Parser` 基类：\n\n```python\nfrom memorymesh.parsing.base import Parser\nfrom memorymesh.core.models import ParsedDocument\n\nclass CustomParser(Parser):\n    @property\n    def supported_extensions(self) -> frozenset[str]:\n        return frozenset({\".custom\"})\n    \n    def parse(self, path: Path) -> ParsedDocument:\n        # 实现解析逻辑\n        return ParsedDocument(\n            path=path,\n            text=processed_text,\n            file_type=\".custom\",\n            metadata={\"source\": \"custom\"},\n        )\n```\n\n## 总结\n\n文件解析器模块是 MemoryMesh 多格式支持的核心，通过统一的 `Parser` 接口和 `ParsedDocument` 数据模型，实现了：\n\n- **格式解耦** - 解析逻辑与索引逻辑分离\n- **自动选择** - 根据扩展名和源类型自动路由\n- **元数据丰富** - 提取格式特定信息供高级检索使用\n- **容错设计** - 编码错误和解析失败不影响整体流程\n\n---\n\n<a id='page-chunkers'></a>\n\n## 文本分块策略\n\n### 相关页面\n\n相关主题：[索引管道](#page-indexing-pipeline), [文件解析器](#page-parsers)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/chunking/base.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/base.py)\n- [src/memorymesh/chunking/recursive.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/recursive.py)\n- [src/memorymesh/chunking/markdown.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/markdown.py)\n- [src/memorymesh/chunking/code.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/code.py)\n- [src/memorymesh/chunking/registry.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/chunking/registry.py)\n</details>\n\n# 文本分块策略\n\n## 概述\n\n文本分块策略是 MemoryMesh 项目中用于将大型文档拆分为可管理单元的核心机制。在 RAG（检索增强生成）系统架构中，分块策略直接影响检索质量和生成效果。MemoryMesh 实现了多种专业化的分块器，每种分块器针对特定内容类型进行优化，确保拆分后的文本块（Chunk）既保持语义完整性，又便于后续的向量检索。\n\n系统通过统一的 `Chunk` 数据模型和抽象基类 `Chunker` 接口，支持灵活的扩展机制。文档解析完成后，相应的分块器会根据文件类型自动选择并应用，实现无缝的文档处理流程。\n\n资料来源：[src/memorymesh/chunking/base.py:1-30]()\n\n## 架构设计\n\n### 核心抽象\n\nMemoryMesh 的分块系统采用策略模式设计，核心组件包括：\n\n```mermaid\ngraph TD\n    A[ParsedDocument] --> B[Chunker Registry]\n    B --> C{Markdown?}\n    B --> D{Code?}\n    B --> E{Default?}\n    C --> F[MarkdownChunker]\n    D --> G[CodeChunker]\n    E --> H[RecursiveChunker]\n    F --> I[Chunk List]\n    G --> I\n    H --> I\n```\n\n`Chunker` 抽象基类定义了统一的分块接口，所有具体分块器都必须实现 `chunk(doc: ParsedDocument) -> list[Chunk]` 方法。这种设计允许在运行时根据文件类型动态选择最合适的分块策略。\n\n资料来源：[src/memorymesh/chunking/base.py:12-18]()\n\n### 分块器类型对比\n\n| 分块器 | 适用场景 | 分割依据 | 依赖项 |\n|--------|----------|----------|--------|\n| MarkdownChunker | Markdown 文档 | ATX 标题层级 | 无 |\n| CodeChunker | 源代码文件 | AST 语法树节点 | tree-sitter-languages |\n| RecursiveChunker | 通用文本 | 字符数/段落/句子 | 无 |\n\n资料来源：[src/memorymesh/chunking/registry.py:44-73]()\n\n## Markdown 分块器\n\n### 工作原理\n\n`MarkdownChunker` 基于 ATX 标题语法（`#`、`##`、`###` 等）对文档进行结构化拆分。每个分块包含一个标题及其下方内容，直到遇到同级或更高级别标题为止。\n\n```mermaid\ngraph LR\n    A[\"# 文档标题\"] --> B[\"## 第一章节<br>章节内容...\"]\n    B --> C[\"## 第二章节<br>章节内容...\"]\n    B --> D[\"### 2.1 子章节<br>子内容...\"]\n    D --> C\n```\n\n系统通过正则表达式 `^(#{1,6})\\s+(.*)` 匹配所有标题行，并维护一个 heading_stack（标题栈）来追踪当前章节的层级关系。\n\n资料来源：[src/memorymesh/chunking/markdown.py:1-50]()\n\n### 标题路径元数据\n\n每个 Markdown 分块都包含 `heading_path` 元数据字段，记录从根标题到当前标题的完整路径。例如，对于 `### 2.1 子章节`，其 `heading_path` 为 `[\"文档标题\", \"第一章节\", \"子章节\"]`。这一特性使搜索命中可以精确定位到文档中的具体位置。\n\n资料来源：[src/memorymesh/chunking/markdown.py:80-85]()\n\n### 溢出拆分机制\n\n当单个章节内容超过 `max_chunk_size`（默认 800 字符）时，`MarkdownChunker` 会调用 `RecursiveChunker` 进行递归拆分，确保最终分块大小符合配置要求。\n\n资料来源：[src/memorymesh/chunking/markdown.py:24-27]()\n\n## 代码分块器\n\n### AST 感知分割\n\n`CodeChunker` 使用 tree-sitter 库解析源代码的抽象语法树（AST），在顶级函数和类定义处进行分割。这种分割方式保持了代码结构完整性，便于检索时代码片段的语义理解。\n\n```mermaid\ngraph TD\n    A[源代码文件] --> B[tree-sitter 解析]\n    B --> C[提取顶级节点]\n    C --> D{节点类型?}\n    D -->|function_definition| E[函数分块]\n    D -->|class_definition| F[类分块]\n    D -->|其他| G[残留代码处理]\n    E --> H[Chunk List]\n    F --> H\n    G --> H\n```\n\n资料来源：[src/memorymesh/chunking/code.py:1-60]()\n\n### 支持的编程语言\n\n| 扩展名 | 语言标识 | 扩展名 | 语言标识 |\n|--------|----------|--------|----------|\n| .py | python | .go | go |\n| .js / .jsx | javascript | .rs | rust |\n| .ts / .tsx | typescript / tsx | .rb | ruby |\n| .java | java | .php | php |\n| .c / .h | c | .swift | swift |\n| .cpp / .hpp | cpp | .kt | kotlin |\n| .cs | c_sharp | | |\n\n资料来源：[src/memorymesh/chunking/code.py:16-36]()\n\n### 分割节点类型\n\n代码分块器在以下 AST 节点类型处进行分割：\n\n- `function_definition`\n- `function_declaration`\n- `method_definition`\n- `class_definition`\n- `class_declaration`\n\n资料来源：[src/memorymesh/chunking/code.py:38-45]()\n\n### 元数据标记\n\n每个代码分块包含丰富的元数据：\n\n- `language`：编程语言名称\n- `function_name`：函数名（如适用）\n- `class_name`：所属类名（如适用）\n\n这些元数据使搜索结果可以精确定位到具体的代码符号。\n\n资料来源：[src/memorymesh/chunking/code.py:95-100]()\n\n### 回退机制\n\n当发生以下情况时，`CodeChunker` 自动回退到 `RecursiveChunker`：\n\n- tree-sitter-languages 未安装\n- 不支持当前文件扩展名\n- tree-sitter 运行时错误\n\n资料来源：[src/memorymesh/chunking/code.py:48-55]()\n\n## 递归分块器\n\n### 层级拆分策略\n\n`RecursiveChunker` 采用多层级递归策略，将文本从大到小逐步拆分，直到满足大小约束。\n\n```mermaid\ngraph TD\n    A[完整文本] --> B{是否超过 chunk_size?}\n    B -->|否| Z[直接返回]\n    B -->|是| C[按段落分割]\n    C --> D{段落是否超过限制?}\n    D -->|是| E[按句子分割]\n    E --> F{句子是否超过限制?}\n    F -->|是| G[按字符数硬截断]\n    G --> H[合并重叠分块]\n    D -->|否| H\n    F -->|否| H\n    H --> I[Chunk List]\n```\n\n资料来源：[src/memorymesh/chunking/recursive.py:1-80]()\n\n### 分割层级\n\n分块器按以下顺序尝试拆分：\n\n1. **段落分割**：按双换行符 `\\n\\n` 分割\n2. **句子分割**：按 `. `、`!`、`?` 等标点分割\n3. **字符截断**：按 `chunk_size` 硬截断\n\n每层拆分后，检查子块是否仍超过大小限制，如是则继续下一层拆分。\n\n资料来源：[src/memorymesh/chunking/recursive.py:30-60]()\n\n### 重叠机制\n\n为保持上下文连续性，相邻分块之间存在 `chunk_overlap`（默认 50 字符）的重叠区域。重叠通过向前回溯实现，确保重要内容不会因分割边界而被切断。\n\n资料来源：[src/memorymesh/chunking/recursive.py:62-70]()\n\n## 分块器注册表\n\n### 文件类型选择逻辑\n\n`ChunkerRegistry` 负责根据文件扩展名选择合适的分块器：\n\n```mermaid\ngraph TD\n    A[输入: extension] --> B{是否为 Markdown 扩展名?}\n    B -->|是| C[返回 MarkdownChunker]\n    B -->|否| D{是否为代码扩展名?}\n    D -->|是| E[返回 CodeChunker]\n    D -->|否| F[返回 RecursiveChunker]\n```\n\nMarkdown 扩展名集合：`.md`、`.mdx`、`.markdown`\n\n代码扩展名集合：`.py`、`.js`、`.jsx`、`.ts`、`.tsx`、`.java`、`.c`、`.cpp`、`.h`、`.hpp`、`.cs`、`.go`、`.rs`、`.rb`、`.php`、`.swift`、`.kt`\n\n资料来源：[src/memorymesh/chunking/registry.py:18-28]()\n\n### 获取分块器接口\n\n```python\ndef get_chunker(\n    extension: str,\n    chunking_config: ChunkingConfig | None = None\n) -> Chunker\n```\n\n当 `chunking_config` 为 `None` 时，使用默认配置参数初始化各分块器。\n\n资料来源：[src/memorymesh/chunking/registry.py:30-73]()\n\n## 配置参数\n\n### 分块配置模型\n\n| 配置项 | 类型 | 默认值 | 说明 |\n|--------|------|--------|------|\n| `max_chunk_size` | int | 800 | Markdown 分块器：单个章节最大字符数 |\n| `chunk_size` | int | - | RecursiveChunker：目标分块大小 |\n| `chunk_overlap` | int | 50 | RecursiveChunker：相邻分块重叠字符数 |\n\n资料来源：[src/memorymesh/chunking/markdown.py:48-50]()\n\n### 配置使用示例\n\n```python\nfrom memorymesh.chunking.registry import get_chunker\nfrom memorymesh.core.models import ChunkingConfig, MarkdownChunkingConfig\n\nconfig = ChunkingConfig(\n    markdown=MarkdownChunkingConfig(max_chunk_size=1000),\n    code=CodeChunkingConfig(max_chunk_size=500),\n    default=RecursiveChunkingConfig(chunk_size=300, chunk_overlap=30)\n)\n\nchunker = get_chunker(\".py\", chunking_config=config)\n```\n\n## 数据模型\n\n### Chunk 数据结构\n\n```python\nclass Chunk(BaseModel):\n    path: Path                      # 源文件绝对路径\n    chunk_index: int                # 文件内分块序号\n    text: str                       # 分块文本内容\n    start_char: int                 # 在源文本中的起始字符偏移\n    end_char: int                   # 在源文本中的结束字符偏移\n    file_type: str                  # 文件类型扩展名\n    mtime: float                    # 文件修改时间戳\n    source_root: str                # 来源配置名称\n    metadata: ChunkMetadata         # 结构化元数据\n```\n\n资料来源：[src/memorymesh/core/models/chunk.py:35-55]()\n\n### ChunkMetadata 元数据\n\n```python\nclass ChunkMetadata(BaseModel):\n    heading_path: list[str] = []    # Markdown 标题路径\n    language: str = \"\"              # 代码语言标识\n    function_name: str = \"\"         # 函数名\n    class_name: str = \"\"            # 类名\n```\n\n资料来源：[src/memorymesh/chunking/markdown.py:82-85]() 和 [src/memorymesh/chunking/code.py:95-100]()\n\n### Chunk ID 标识符\n\n每个 Chunk 具有稳定的唯一标识符，格式为 `<path>:<chunk_index>`，便于跨系统引用和去重。\n\n资料来源：[src/memorymesh/core/models/chunk.py:57-59]()\n\n## 最佳实践\n\n### 调整分块大小\n\n| 使用场景 | 推荐配置 |\n|----------|----------|\n| 细粒度检索（如代码搜索） | `max_chunk_size=300-500` |\n| 文档问答 | `max_chunk_size=800-1000` |\n| 长文档摘要 | `max_chunk_size=1500+` |\n\n### 选择分块策略\n\n- **结构化文档**（Markdown）：优先使用 `MarkdownChunker` 保留文档结构\n- **源代码**：使用 `CodeChunker` 保持函数/类完整性\n- **非结构化文本**：使用 `RecursiveChunker` 按语义层级拆分\n\n---\n\n<a id='page-search-engine'></a>\n\n## 搜索引擎\n\n### 相关页面\n\n相关主题：[系统架构](#page-architecture), [结果重排序](#page-reranking), [MCP 工具参考](#page-mcp-tools)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/search/engine.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/engine.py)\n- [src/memorymesh/search/rank_fusion.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/rank_fusion.py)\n- [src/memorymesh/search/query_expander.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/query_expander.py)\n- [src/memorymesh/llm/ollama_client.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/llm/ollama_client.py)\n- [src/memorymesh/server/tools/ask_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/ask_memory.py)\n- [CHANGELOG.md](https://github.com/kilhubprojects/memory-mesh/blob/main/CHANGELOG.md)\n- [src/memorymesh/server/dashboard.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/dashboard.py)\n- [ARCHITECTURE.md](https://github.com/kilhubprojects/memory-mesh/blob/main/ARCHITECTURE.md)\n</details>\n\n# 搜索引擎\n\n## 1. 概述\n\nMemoryMesh 的搜索引擎是一个混合检索系统，支持密集检索（dense retrieval）和稀疏检索（sparse retrieval）两种方式，并提供可选的重排序（reranking）和查询扩展（query expansion）功能。该引擎是整个知识库问答系统的核心，负责从向量数据库中快速定位相关文本块。\n\n搜索引擎的核心职责包括：\n\n- 接收用户查询文本\n- 通过查询扩展生成语义变体\n- 并行执行多种检索策略\n- 使用排名融合（rank fusion）整合多路检索结果\n- 可选地通过 LLM 进行结果重排序\n- 返回排序后的搜索命中列表\n\n资料来源：[CHANGELOG.md]()\n\n## 2. 架构设计\n\n### 2.1 整体架构图\n\n```mermaid\ngraph TD\n    A[用户查询] --> B[查询扩展 QueryExpander]\n    B --> C[生成多个查询变体]\n    C --> D[并行检索 Pipeline]\n    D --> E[密集检索 Dense Retriever]\n    D --> F[稀疏检索 Sparse Retriever]\n    E --> G[排名融合 RankFusion]\n    F --> G\n    G --> H[可选: 重排序 Reranker]\n    H --> I[SearchHit 结果列表]\n    \n    J[Ollama LLM] -.-> H\n    K[向量数据库] -.-> E\n    L[元数据存储] -.-> F\n```\n\n### 2.2 核心组件\n\n| 组件 | 文件路径 | 职责 |\n|------|----------|------|\n| SearchEngine | `search/engine.py` | 主编排引擎，协调整个检索流程 |\n| QueryExpander | `search/query_expander.py` | 查询扩展，生成语义变体 |\n| RankFusion | `search/rank_fusion.py` | 多路结果融合 |\n| OllamaClient | `llm/ollama_client.py` | 本地 LLM 调用接口 |\n| AskMemory | `server/tools/ask_memory.py` | MCP 工具封装 |\n\n资料来源：[CHANGELOG.md]()\n\n## 3. 检索策略\n\n### 3.1 并行变体检索\n\nSearchEngine 使用 `ThreadPoolExecutor` 实现并行检索。针对扩展后的多个查询变体，系统会并发地向向量数据库发起检索请求，最后将所有结果汇总。这一设计显著提升了长查询的检索效率。\n\n```python\n# 伪代码展示并行检索逻辑\ndef _retrieve_single(self, variant_query: str) -> list[SearchHit]:\n    \"\"\"执行单个查询变体的检索\"\"\"\n\ndef _fuse_all(self, all_hits: list[list[SearchHit]]) -> list[SearchHit]:\n    \"\"\"融合多路检索结果\"\"\"\n```\n\n资料来源：[CHANGELOG.md]()\n\n### 3.2 密集检索与稀疏检索\n\n系统支持两种互补的检索模式：\n\n- **密集检索（Dense Retrieval）**：使用文本嵌入模型将查询和文档都编码为向量，在向量空间中进行相似度搜索，适合语义匹配。\n- **稀疏检索（Sparse Retrieval）**：基于关键词的传统 BM25 或类似算法，适合精确术语匹配。\n\n两种检索结果通过排名融合算法整合，兼顾语义理解和精确匹配。\n\n### 3.3 摘要块过滤\n\n系统支持在索引阶段生成摘要块（`chunk_type=\"summary\"`），这些摘要块存储在向量数据库中用于提升抽象语义召回率。但在搜索结果返回时，摘要块会被自动过滤掉，不会直接暴露给用户。\n\n资料来源：[CHANGELOG.md]()\n\n## 4. 查询扩展\n\nQueryExpander 负责将用户原始查询扩展为多个语义变体，以提升检索的召回率。\n\n### 4.1 配置参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `n_lexical_variants` | 生成的词汇变体数量 | 1 |\n| `expansion_model` | 使用的扩展模型 | - |\n\n在最新版本中，`n_lexical_variants` 的默认值从 2 降低到 1，以减少查询噪声。\n\n资料来源：[CHANGELOG.md]()\n\n### 4.2 扩展流程\n\n```mermaid\ngraph LR\n    A[原始查询] --> B[语义分析]\n    B --> C[生成变体1]\n    B --> D[生成变体2]\n    C --> E[合并为查询列表]\n    D --> E\n    E --> F[并行检索]\n```\n\n## 5. 排名融合\n\n当多路检索返回结果后，RankFusion 模块负责将不同检索策略的结果合并为统一的排序列表。\n\n### 5.1 融合策略\n\n融合算法会考虑每个命中结果在不同检索通道中的排名位置，给予排名靠前的结果更高的融合分数。最终返回一个综合排序后的 `SearchHit` 列表。\n\n## 6. 重排序（Reranking）\n\n### 6.1 简介\n\n可选的重排序功能使用 LLM 对初筛结果进行二次排序，以提升结果相关性。\n\n### 6.2 配置参数\n\n| 参数 | 说明 | 默认值 |\n|------|------|--------|\n| `top_k_before_rerank` | 重排序前保留的候选结果数 | 35 |\n| `model` | 使用的重排序模型 | - |\n\n该参数默认值从 20 提高到 35，以防止长描述性查询中的相关文件在重排序前被错误排除。\n\n资料来源：[CHANGELOG.md]()\n\n## 7. 搜索工具（Ask Memory MCP）\n\nAsk Memory 是一个 MCP（Model Context Protocol）工具，封装了搜索引擎用于 AI 对话助手的问答场景。\n\n### 7.1 工作流程\n\n```mermaid\ngraph TD\n    A[用户问题] --> B[混合检索]\n    B --> C[上下文组装]\n    C --> D[Ollama Generate]\n    D --> E[返回答案 + 引用来源]\n    \n    F[Ollama 不可用] -.-> G[返回来源列表 + 安装提示]\n    G --> E\n```\n\n### 7.2 返回格式\n\n```python\nclass AskMemoryResponse:\n    answer: str | None       # LLM 生成的回答\n    sources: list[SearchHit] # 搜索命中文档\n    model: str               # 使用的模型名称\n    ollama_available: bool   # Ollama 是否可用\n    hint: str | None         # 仅在不可用时返回\n```\n\n### 7.3 降级策略\n\n当 Ollama 本地 LLM 服务不可用时，系统会优雅降级：返回原始搜索结果列表，并在响应中包含安装提示（hint），确保不会因 LLM 不可用而完全失败。\n\n资料来源：[ARCHITECTURE.md]()\n\n## 8. Web 界面\n\n### 8.1 搜索页面\n\nMemoryMesh 提供基于 FastAPI + HTMX 的 Web 搜索界面，支持用户直接输入查询词进行搜索。搜索结果以 HTML 形式渲染展示。\n\n### 8.2 路由定义\n\n| 路由 | 方法 | 功能 |\n|------|------|------|\n| `/search` | GET/POST | 搜索页面，支持 `mode` 参数（dense/sparse/hybrid） |\n\n```html\n<!-- 搜索表单示例 -->\n<form method=\"get\" action=\"/search\">\n  <input name=\"q\" placeholder=\"输入搜索内容...\">\n  <select name=\"mode\">\n    <option value=\"hybrid\" selected>Hybrid</option>\n    <option value=\"dense\">Dense</option>\n    <option value=\"sparse\">Sparse</option>\n  </select>\n  <button type=\"submit\">Search</button>\n</form>\n```\n\n资料来源：[src/memorymesh/server/dashboard.py]()\n\n## 9. 配置示例\n\n在 `config.yaml` 中配置搜索相关参数：\n\n```yaml\nsearch:\n  embedding_model: sentence-transformers/all-MiniLM-L6-v2\n  dense:\n    top_k: 10\n  sparse:\n    top_k: 10\n  reranker:\n    enabled: true\n    top_k_before_rerank: 35\n  query_expansion:\n    enabled: true\n    n_lexical_variants: 1\n```\n\n## 10. 依赖关系\n\n| 依赖项 | 用途 |\n|--------|------|\n| `sentence-transformers` | 文本嵌入模型 |\n| `faiss` 或 `chromadb` | 向量数据库 |\n| `Ollama` | 本地 LLM 推理 |\n| `fastapi` | Web 服务框架 |\n| `httpx` | HTTP 客户端 |\n\n## 11. 相关文档\n\n- [架构总览](./ARCHITECTURE.md)\n- [配置指南](./CONFIG.md)\n- [API 参考](./API.md)\n- [MCP 工具文档](./MCP_TOOLS.md)\n\n---\n\n<a id='page-reranking'></a>\n\n## 结果重排序\n\n### 相关页面\n\n相关主题：[搜索引擎](#page-search-engine)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/search/reranker.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/reranker.py)\n- [src/memorymesh/core/models/config.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/config.py)\n- [src/memorymesh/search/engine.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/engine.py)\n- [src/memorymesh/search/models.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/search/models.py)\n- [CHANGELOG.md](https://github.com/kilhubprojects/memory-mesh/blob/main/CHANGELOG.md)\n- [ARCHITECTURE.md](https://github.com/kilhubprojects/memory-mesh/blob/main/ARCHITECTURE.md)\n</details>\n\n# 结果重排序\n\n结果重排序（Result Reranking）是 MemoryMesh 搜索系统中提升检索精度的核心机制。该模块在完成初步检索后，通过交叉编码器（Cross-Encoder）对候选结果进行深度语义相关性评分，从而修正纯向量检索可能产生的排序偏差。\n\n## 工作原理\n\nMemoryMesh 采用典型的两阶段检索架构：**密集检索（Dense Retrieval）** → **结果重排序（Reranking）**。\n\n```mermaid\ngraph TD\n    A[用户查询] --> B[密集检索阶段]\n    B --> C[召回 Top-N 候选结果<br/>top_k_before_rerank]\n    C --> D[重排序阶段]\n    D --> E[交叉编码器评分]\n    E --> F[按相关性重新排序]\n    F --> G[返回 Top-K 最终结果<br/>top_k]\n    C -.->|候选集过大<br/>影响精度| D\n```\n\n第一阶段使用密集向量检索快速从大规模语料中召回候选文档；第二阶段通过语义更精准的交叉编码器对候选集进行细粒度排序，最终输出高相关性的结果列表。\n\n资料来源：[ARCHITECTURE.md:1-50]()\n\n## 配置参数\n\n重排序功能通过 `SearchRerankerConfig` 进行配置，主要参数如下：\n\n| 参数 | 类型 | 默认值 | 说明 |\n|------|------|--------|------|\n| `enabled` | `bool` | `True` | 是否启用重排序 |\n| `model` | `str` | `\"cross-encoder\"` | 交叉编码器模型标识 |\n| `top_k_before_rerank` | `int` | `35` | 重排序前保留的候选结果数量 |\n| `top_k` | `int` | `5` | 最终返回的结果数量 |\n\n> **配置变更历史**：在 v1.2.0 版本中，`top_k_before_rerank` 的默认值从 `20` 提升至 `35`。此调整旨在防止长描述性查询中相关文档在重排序前被过早过滤，从而提升召回率。\n\n资料来源：[src/memorymesh/core/models/config.py:1-100]()\n资料来源：[CHANGELOG.md:1-50]()\n\n## 交叉编码器模型\n\n重排序阶段使用的交叉编码器接收查询与文档对（query-document pair），输出单一相关性分数。相比于双编码器（Bi-Encoder）分别编码查询和文档的方式，交叉编码器能够在注意力机制中直接建模两者的交互关系，从而捕获更精细的语义关联。\n\n```mermaid\ngraph LR\n    subgraph 交叉编码器\n        Q[Query Token序列] -->|拼接| M[联合输入]\n        D[Document Token序列] -->|拼接| M\n        M --> AT[Attention层]\n        AT --> FC[全连接层]\n        FC --> S[相关性分数: 0-1]\n    end\n```\n\n模型输出范围为 0 到 1 的浮点数，其中：\n- `1.0` 表示极高相关性\n- `0.0` 表示完全不相关\n\n资料来源：[src/memorymesh/search/reranker.py:1-80]()\n\n## 搜索流程集成\n\n重排序模块嵌入在 `SearchEngine` 的完整检索管线中：\n\n```mermaid\ngraph TD\n    A[search_query] --> B[QueryExpansion]\n    B --> C[并行向量检索<br/>ThreadPoolExecutor]\n    C --> D[融合多路检索结果]\n    D --> E{top_k_before_rerank<br/>≥ top_k?}\n    E -->|是| F[交叉编码器重排序]\n    F --> G[返回Top-K结果]\n    E -->|否| G\n```\n\n> **并行优化**：`SearchEngine` 已使用 `ThreadPoolExecutor` 实现多路查询变体的并行检索，提升整体响应速度。\n\n资料来源：[src/memorymesh/search/engine.py:1-100]()\n资料来源：[CHANGELOG.md:30-40]()\n\n## 与其他搜索组件的关系\n\n| 组件 | 作用阶段 | 输入 | 输出 |\n|------|----------|------|------|\n| QueryExpansion | 预处理 | 用户原始查询 | 扩展查询变体列表 |\n| EmbeddingProvider | 密集检索 | 查询文本 | 向量表示 |\n| VectorStore | 检索 | 查询向量 | Top-N 候选文档 |\n| **Reranker** | **重排序** | **候选文档 + 查询** | **重排序后的文档列表** |\n| SearchReranker | 最终封装 | 重排序结果 | SearchHit 列表 |\n\n资料来源：[src/memorymesh/search/models.py:1-50]()\n\n## 使用示例\n\n```python\nfrom memorymesh.core.models.config import SearchConfig, SearchRerankerConfig\nfrom memorymesh.search.engine import SearchEngine\n\n# 配置重排序参数\nreranker_cfg = SearchRerankerConfig(\n    enabled=True,\n    top_k_before_rerank=35,\n    top_k=5,\n)\n\nsearch_cfg = SearchConfig(\n    top_k=5,\n    reranker=reranker_cfg,\n)\n\n# 初始化搜索引擎\nengine = SearchEngine(config=search_cfg, ...)\n\n# 执行搜索（自动触发重排序）\nresults = engine.search(\"项目架构设计原则\")\n```\n\n## 性能考量\n\n1. **候选集大小权衡**：`top_k_before_rerank` 过小可能导致遗漏相关文档，过大则增加交叉编码器的计算开销。默认值 `35` 在大多数场景下取得较好平衡。\n\n2. **模型选择**：交叉编码器模型直接影响重排序质量与推理速度。生产环境可根据硬件条件选择轻量级或高精度模型。\n\n3. **异步支持**：重排序阶段可与密集检索并行执行，通过合理的调度策略进一步降低端到端延迟。\n\n资料来源：[ARCHITECTURE.md:50-100]()\n\n## 配置示例\n\n```yaml\nsearch:\n  top_k: 5\n  reranker:\n    enabled: true\n    model: \"cross-encoder/ms-marco-MiniLM-L-6-v2\"\n    top_k_before_rerank: 35\n```\n\n该配置启用重排序功能，使用 `ms-marco-MiniLM-L-6-v2` 交叉编码器模型，在重排序前保留 35 个候选结果，最终返回 5 条最相关文档。\n\n---\n\n<a id='page-connectors'></a>\n\n## 数据连接器\n\n### 相关页面\n\n相关主题：[MCP 工具参考](#page-mcp-tools)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/connectors/registry.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/registry.py)\n- [src/memorymesh/connectors/confluence_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/confluence_connector.py)\n- [src/memorymesh/connectors/roam_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/roam_connector.py)\n- [src/memorymesh/connectors/logseq_connector.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/connectors/logseq_connector.py)\n- [src/memorymesh/parsing/obsidian_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/obsidian_parser.py)\n- [src/memorymesh/parsing/notion_parser.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/parsing/notion_parser.py)\n</details>\n\n# 数据连接器\n\n## 概述\n\n数据连接器（Connector）是 MemoryMesh 系统用于从外部数据源提取文档的核心模块。每个连接器实现特定平台的协议解析与数据拉取，将来自不同知识管理工具的原始数据转换为统一的 `ParsedDocument` 数据模型。\n\n连接器的设计遵循以下原则：\n\n- **统一接口** - 所有连接器实现 `fetch_documents()` 方法，返回 `Iterator[ParsedDocument]`\n- **配置驱动** - 每个连接器配套一个 Pydantic 配置类，通过 `config.yaml` 声明式配置\n- **懒加载注册** - 连接器通过 `CONNECTOR_REGISTRY` 字典按需注册，最小化导入开销\n- **解析器协同** - 部分连接器（如 Notion、Obsidian）依赖配套的解析器完成文件级别的数据转换\n\n资料来源：[src/memorymesh/connectors/registry.py:1-20]()\n\n## 架构设计\n\n### 组件关系图\n\n```mermaid\ngraph TD\n    A[config.yaml] --> B[ConnectorConfig]\n    B --> C[Connector]\n    C --> D{fetch_documents}\n    D --> E[Iterator[ParsedDocument]]\n    E --> F[FileIndexer]\n    F --> G[Chunker]\n    G --> H[EmbeddingProvider]\n    H --> I[VectorStore]\n    \n    J[CONNECTOR_REGISTRY] --> C\n    K[HTTP Auth] --> C\n```\n\n### 连接器类型矩阵\n\n| 类型标识 | 连接器类 | 配置类 | 数据源 | 认证方式 |\n|---------|---------|-------|--------|---------|\n| `confluence` | ConfluenceConnector | ConfluenceConfig | Confluence Cloud REST API | HTTP Basic |\n| `roam` | RoamConnector | RoamConfig | JSON 导出文件 | 无（本地文件） |\n| `logseq` | LogseqConnector | LogseqConfig | Graph 目录 | 无（本地文件） |\n| `notion` | NotionConnector | NotionConfig | Notion API | OAuth/API Token |\n| `jira` | JiraConnector | JiraConfig | Jira REST API | HTTP Basic |\n\n资料来源：[src/memorymesh/connectors/registry.py:25-50]()\n\n## 连接器注册机制\n\n### 注册表结构\n\n`CONNECTOR_REGISTRY` 是一个字典，将连接器类型字符串映射到 `(ConfigClass, ConnectorClass)` 元组：\n\n```python\nCONNECTOR_REGISTRY: dict[str, tuple[Any, Any]] = {}\n```\n\n注册在 `_register()` 函数中通过延迟导入完成，避免在模块初始化时导入所有依赖：\n\n```python\ndef _register() -> None:\n    \"\"\"Populate CONNECTOR_REGISTRY with all known connectors.\"\"\"\n    from memorymesh.connectors.airtable_connector import (\n        AirtableConfig,\n        AirtableConnector,\n    )\n    # ... 其他连接器导入\n```\n\n资料来源：[src/memorymesh/connectors/registry.py:15-40]()\n\n### 使用方式\n\nCLI 命令通过注册表动态实例化连接器：\n\n```python\ncfg_cls, conn_cls = CONNECTOR_REGISTRY[\"jira\"]\nconfig_obj = cfg_cls(**raw_config_dict)\nconnector = conn_cls(config_obj)\nfor doc in connector.fetch_documents():\n    indexer.index_parsed_document(doc)\n```\n\n## Confluence 连接器\n\n### 功能特性\n\n- **偏移分页** - 通过 `start` / `limit` 参数迭代获取所有页面\n- **空间过滤** - 可选限制特定空间密钥（space keys）\n- **HTML 清洗** - 将 `storage` 格式的页面体转换为纯文本\n- **日期过滤** - 跳过 `days_past` 时间窗口外的页面\n\n资料来源：[src/memorymesh/connectors/confluence_connector.py:1-30]()\n\n### 配置参数\n\n| 参数 | 类型 | 必填 | 说明 |\n|-----|------|-----|------|\n| `base_url` | str | 是 | Confluence Cloud 实例 URL |\n| `email` | SecretStr | 是 | Atlassian 账户邮箱 |\n| `api_token` | SecretStr | 是 | API Token（从 id.atlassian.com 生成） |\n| `space_keys` | list[str] | 否 | 限制的空间密钥列表 |\n| `days_past` | int | 否 | 保留最近 N 天内的页面（默认 90） |\n\n### 认证实现\n\nHTTP Basic 认证使用 `email:api_token` 组合的 base64 编码：\n\n```python\nfrom memorymesh.connectors._auth import basic_header\n```\n\n资料来源：[src/memorymesh/connectors/confluence_connector.py:40-45]()\n\n## Roam Research 连接器\n\n### 功能特性\n\n- **递归块扁平化** - 将嵌套块树展平为纯文本字符串\n- **Roam 语法清洗** - 移除 `{{[[...]]}}` 模板引用、`[[...]]` 页面引用、`#[[...]]` 和 `#tag` 标签语法\n- **日期过滤** - 跳过 `create-time` 或 `edit-time` 超出 `days_past` 窗口的页面\n- **空页面跳过** - 跳过无块内容的页面\n\n资料来源：[src/memorymesh/connectors/roam_connector.py:1-35]()\n\n### 导出格式\n\nRoam 导出为单个 JSON 文件，包含页面对象数组，每个对象具有：\n\n- `title` - 字符串\n- `children` - 嵌套块对象列表（块可递归包含 `children`）\n\n### 语法模式处理\n\n按顺序应用多个正则表达式清洗 Roam 特定语法：\n\n```python\n_ROAM_PATTERNS: list[re.Pattern[str]] = [\n    re.compile(r\"\\{\\{(\\[\\[.*?\\]\\])\"),  # 模板引用\n    re.compile(r\"\\[\\[.*?\\]\\]\"),        # 页面引用\n    re.compile(r\"#\\[\\[.*?\\]\\]\"),       # 标签页面引用\n    re.compile(r\"#\\w+\"),               # 标签\n]\n```\n\n资料来源：[src/memorymesh/connectors/roam_connector.py:55-60]()\n\n## Logseq 连接器\n\n### 功能特性\n\n- **多目录扫描** - 扫描 `pages/` 和 `journals/` 子目录\n- **语法转换** - 处理 Logseq 特定语法\n- **属性提取** - 从 `key:: value` 属性行提取元数据\n- **维基链接追踪** - 提取并去重的 `[[wikilinks]]` 存储在元数据中\n- **日记标记** - 期刊文件标记 `is_journal=True`\n\n资料来源：[src/memorymesh/connectors/logseq_connector.py:1-40]()\n\n### Logseq 语法处理对照表\n\n| 原始语法 | 处理方式 | 示例 |\n|---------|---------|------|\n| `((uuid))` | 转换为 `[block]` | `((abc123...))` → `[block]` |\n| `{{embed [[Page]]}}` | 转换为 `[embed: Page]` | `{{embed [[Note]]}}` → `[embed: Note]` |\n| `{{query ...}}` | 完全移除 | `{{query [[tag]]}}` → 移除 |\n| `key:: value` | 提取到元数据，从正文移除 | `tags:: #work` → metadata[\"tags\"] |\n| `[[wikilinks]]` | 保留原样 | `[[Page A]]` → `[[Page A]]` |\n| `- ` 块符号 | 保留为纯文本 | `- content` → `content` |\n\n资料来源：[src/memorymesh/connectors/logseq_connector.py:45-70]()\n\n### 文档处理流程\n\n```mermaid\ngraph LR\n    A[Markdown 文件] --> B[_process_file]\n    B --> C{文件存在?}\n    C -->|否| D[跳过]\n    C -->|是| E[读取文本]\n    E --> F[正则替换]\n    F --> G[属性提取]\n    G --> H[Wikilinks 提取]\n    H --> I[ParsedDocument]\n```\n\n资料来源：[src/memorymesh/connectors/logseq_connector.py:90-120]()\n\n## 配套解析器\n\n部分数据源需要专门的解析器处理文件格式，而非通过连接器直接拉取。\n\n### Notion HTML 解析器\n\nNotion 导出为单个 `.html` 文件，解析器从文件名提取 UUID、从 `<h1>` 或 `<title>` 提取标题：\n\n```python\n# UUID 模式：Page Title a1b2c3...html\n_UUID_FILENAME_RE = re.compile(\n    r\"([0-9a-f]{8}(?:[0-9a-f]{4}){3}[0-9a-f]{12})(?:\\s|\\.|$)\",\n    re.IGNORECASE,\n)\n```\n\n支持扩展名：`.html`, `.htm`\n\n提取的元数据字段：\n\n- `notion_id` - 页面 UUID\n- `database_name` - 父目录名\n- `db_properties` - 数据库属性列表\n\n资料来源：[src/memorymesh/parsing/notion_parser.py:25-45]()\n\n### Obsidian Markdown 解析器\n\nObsidian 解析器扩展基础 Markdown 解析：\n\n| 功能 | 说明 |\n|-----|------|\n| YAML Frontmatter | 提取 `tags`、`aliases`、`created`、`modified` 字段 |\n| Wikilink 提取 | 匹配 `[[link]]` 和 `[[link\\|alias]]` 模式 |\n| 内嵌过滤 | 排除 `![[img]]` 图片引用 |\n| 标签提取 | 从 frontmatter 和行内 `#tag` 提取标签 |\n\n支持的 frontmatter 字段映射：\n\n| Frontmatter 字段 | Metadata 键 |\n|----------------|------------|\n| `tags` | `tags` |\n| `aliases` | `aliases` |\n| `created` | `created` |\n| `modified` | `modified` |\n\n资料来源：[src/memorymesh/parsing/obsidian_parser.py:25-55]()\n\n### Frontmatter 解析正则\n\n```python\n_FRONTMATTER_RE = re.compile(\n    r\"^---\\r?\\n(.*?)\\r?\\n(?:---|\\.\\.\\.)(?:\\r?\\n|$)\",\n    re.DOTALL,\n)\n_WIKILINK_RE = re.compile(r\"(?<!!)\\[\\[([^\\[\\]|#]+?)(?:\\|[^\\[\\]]*?)?\\]\\]\")\n```\n\n## HTTP 辅助模块\n\n### 认证模块 (`_auth.py`)\n\n提供基础认证头生成：\n\n```python\nfrom memorymesh.connectors._auth import basic_header\n```\n\n支持标准 HTTP Basic 认证，用于 Confluence、Jira 等需要用户名/令牌的服务。\n\n### HTTP 模块 (`_http.py`)\n\n提供统一的 API 请求方法：\n\n```python\nfrom memorymesh.connectors._http import api_get\n```\n\n主要功能：\n\n- 自动添加认证头\n- 错误处理与日志记录\n- JSON 响应解析\n\n## 通用数据模型\n\n### ParsedDocument 结构\n\n所有连接器返回统一的 `ParsedDocument` 对象：\n\n| 字段 | 类型 | 说明 |\n|-----|------|------|\n| `path` | Path | 文件路径 |\n| `text` | str | 提取的纯文本内容 |\n| `file_type` | str | 规范化扩展名（如 `.md`、`.html`） |\n| `encoding` | str | 文本编码 |\n| `metadata` | dict | 源特定元数据 |\n\n### 配置基类模式\n\n每个连接器遵循统一配置模式：\n\n```python\nfrom pydantic import BaseModel\n\nclass ConnectorConfig(BaseModel):\n    export_path: Path | None = None      # 本地文件模式\n    days_past: int = 365                 # 日期过滤窗口\n```\n\n## 使用示例\n\n### 配置声明\n\n在 `config.yaml` 中声明数据源：\n\n```yaml\nsources:\n  - name: confluence-wiki\n    type: confluence\n    config:\n      base_url: \"https://myorg.atlassian.net\"\n      email: \"me@example.com\"\n      api_token: \"${CONFLUENCE_TOKEN}\"\n      space_keys: [\"ENG\", \"DOCS\"]\n      days_past: 90\n```\n\n### 代码使用\n\n```python\nfrom memorymesh.connectors.registry import CONNECTOR_REGISTRY\n\n# 通过注册表实例化\ncfg_cls, conn_cls = CONNECTOR_REGISTRY[\"confluence\"]\nconfig = cfg_cls(**source_config[\"config\"])\nconnector = conn_cls(config)\n\n# 迭代文档\nfor doc in connector.fetch_documents():\n    indexer.index_parsed_document(doc)\n```\n\n## 扩展新连接器\n\n添加新连接器的步骤：\n\n1. **创建连接器文件** - 在 `src/memorymesh/connectors/` 下创建 `xxx_connector.py`\n2. **定义配置类** - 创建 `XxxConfig(BaseModel)` 配置模型\n3. **实现连接器类** - 创建 `XxxConnector` 实现 `fetch_documents()` 方法\n4. **注册连接器** - 在 `registry.py` 的 `_register()` 函数中添加导入语句\n\n```mermaid\ngraph TD\n    A[创建 xxx_connector.py] --> B[定义 XxxConfig]\n    B --> C[实现 XxxConnector]\n    C --> D[实现 fetch_documents]\n    D --> E[更新 registry.py]\n```\n\n## 注意事项\n\n- **认证安全** - API Token 等敏感信息建议使用环境变量注入（`${VAR_NAME}` 语法）\n- **文件锁定** - 本地文件模式（如 Roam、Logseq）直接读取文件，注意并发写入\n- **分页处理** - API 类连接器需妥善处理分页，避免漏掉数据\n- **日期时区** - 日期比较使用 `datetime` 模块，配置 `UTC` 时区处理\n\n---\n\n<a id='page-mcp-tools'></a>\n\n## MCP 工具参考\n\n### 相关页面\n\n相关主题：[搜索引擎](#page-search-engine), [数据连接器](#page-connectors)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/memorymesh/server/tools/search_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/search_memory.py)\n- [src/memorymesh/server/tools/ask_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/ask_memory.py)\n- [src/memorymesh/server/tools/list_sources.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/list_sources.py)\n- [src/memorymesh/server/tools/get_document.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/get_document.py)\n- [src/memorymesh/server/tools/graph_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/graph_memory.py)\n- [src/memorymesh/server/tools/pin_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/pin_memory.py)\n- [src/memorymesh/server/tools/forget_memory.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/tools/forget_memory.py)\n- [src/memorymesh/server/app.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/server/app.py)\n- [src/memorymesh/core/models/search.py](https://github.com/kilhubprojects/memory-mesh/blob/main/src/memorymesh/core/models/search.py)\n</details>\n\n# MCP 工具参考\n\nMemoryMesh 通过 FastMCP 框架提供一组 MCP（Model Context Protocol）工具，使 LLM 客户端能够访问用户的本地知识库。所有工具均注册在 `FastMCP` 实例上，支持搜索、检索、索引管理、内存分层和知识图谱查询等核心功能。\n\n## 工具概览\n\nMemoryMesh MCP 工具分为以下几大类：\n\n| 类别 | 工具 | 功能描述 |\n|------|------|----------|\n| **搜索检索** | `search_memory` | 混合检索（向量 + BM25） |\n| | `ask_memory` | RAG 问答（基于 Ollama） |\n| | `search_by_date` | 按时间范围检索 |\n| | `related_documents` | 查找相关文档 |\n| **文档管理** | `list_sources` | 列出配置的索引源 |\n| | `get_document` | 获取完整文档内容 |\n| | `summarize_source` | 生成文档摘要 |\n| **索引控制** | `index_now` | 触发立即重建索引 |\n| | `sync_source` | 同步数据源 |\n| **内存分层** | `pin_memory` | 将分块固定到热层 |\n| | `unpin_memory` | 解除固定 |\n| | `forget_memory` | 抑制或冷置分块 |\n| **知识图谱** | `graph_memory` | 共现图查询 |\n| | `get_entity` | 获取实体信息 |\n| **时间线** | `query_timeline` | 查询活动历史 |\n\n资料来源：[src/memorymesh/server/app.py:36-52]()\n\n## 工具注册机制\n\n所有 MCP 工具通过统一的注册函数 `register(mcp, ctx)` 挂载到 FastMCP 实例：\n\n```python\ndef create_mcp(ctx: AppContext) -> FastMCP:\n    mcp: FastMCP = FastMCP(\n        name=\"memorymesh\",\n        instructions=(\n            \"MemoryMesh gives you read access to the user's personal knowledge \"\n            \"base — local files indexed from configured source directories.  \"\n            \"Use search_memory to find relevant passages, list_sources to \"\n            \"explore what has been indexed, get_document to read a full file, \"\n            \"index_now to trigger an immediate re-index, and ask_memory to \"\n            \"get an LLM-generated answer from your indexed content...\"\n        ),\n    )\n    \n    # 注册所有工具\n    search_memory.register(mcp, ctx)\n    list_sources.register(mcp, ctx)\n    get_document.register(mcp, ctx)\n    index_now.register(mcp, ctx)\n    ask_memory.register(mcp, ctx)\n    # ... 其他工具\n```\n\n工具注册采用依赖注入模式，`ctx`（AppContext）包含所有运行时依赖：搜索引擎、元数据存储、审计日志等。\n\n## 搜索检索类工具\n\n### search_memory\n\n混合检索工具，结合密集向量检索（embedding）和稀疏 BM25 检索。\n\n**函数签名：**\n\n```python\n@mcp.tool()\nasync def search_memory(\n    query: Annotated[str, \"要搜索的自然语言查询\"],\n    top_k: Annotated[int, \"返回的最大结果数\"] = 5,\n    mode: Annotated[\n        Literal[\"hybrid\", \"dense\", \"sparse\"],\n        \"hybrid: 密集+稀疏混合; dense: 仅向量; sparse: 仅BM25\"\n    ] = \"hybrid\",\n    source_filter: Annotated[\n        list[str] | None,\n        \"限制搜索的源名称列表\"\n    ] = None,\n    modality: Annotated[\n        Literal[\"all\", \"text\", \"image\"],\n        \"搜索的模态类型\"\n    ] = \"all\",\n) -> SearchResponse\n```\n\n**返回类型（SearchResponse）：**\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `hits` | `list[SearchHit]` | 排序后的搜索结果列表 |\n| `mode` | `\"hybrid\" \\| \"dense\" \\| \"sparse\"` | 使用的检索模式 |\n| `duration_ms` | `float` | 查询总延迟（毫秒） |\n\n资料来源：[src/memorymesh/core/models/search.py:1-30]()\n\n### ask_memory\n\nRAG 问答工具，基于 Ollama 本地 LLM 生成答案。\n\n**核心机制：**\n\n```\n用户问题 → search_memory → 构建上下文 → Ollama generate → 答案 + 引用源\n```\n\n**函数签名：**\n\n```python\n@mcp.tool()\nasync def ask_memory(\n    question: str,\n    top_k: int = 5,\n    model: str | None = None,\n) -> AskMemoryResponse\n```\n\n**上下文构建参数：**\n\n- `_MAX_CONTEXT_CHARS_PER_HIT = 800`：每个来源片段最多包含 800 字符\n\n**系统提示词模板：**\n\n```python\n_RAG_SYSTEM_PREAMBLE = (\n    \"You are a helpful assistant answering questions about the user's personal \"\n    \"knowledge base. Use only the provided source passages to answer. \"\n    \"If the answer is not in the sources, say so clearly. \"\n    \"Cite the source file paths when relevant.\"\n)\n```\n\n**返回类型（AskMemoryResponse）：**\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `answer` | `str \\| None` | LLM 生成的答案 |\n| `sources` | `list[SearchHit]` | 检索到的来源片段 |\n| `model` | `str` | 使用的 Ollama 模型 |\n| `ollama_available` | `bool` | Ollama 是否可用 |\n| `hint` | `str \\| None` | 仅在 Ollama 不可用时返回安装提示 |\n\n> **容错设计**：当 Ollama 不可用时，`ask_memory` 仍返回检索结果和安装提示，绝不静默失败。\n\n资料来源：[src/memorymesh/server/tools/ask_memory.py:1-50]()\n\n### search_by_date\n\n按时间范围检索文档变更历史。\n\n**典型用途：** 查找特定时间段内修改过的文件内容。\n\n### related_documents\n\n基于共现关系查找相关文档，输入一个 chunk_id，返回与其在相同上下文中出现的其他文档。\n\n## 文档管理类工具\n\n### list_sources\n\n列出所有配置的索引源及其统计信息。\n\n**返回类型（SourcesReport）：**\n\n```python\nclass SourcesReport(BaseModel):\n    sources: list[SourceStats]\n\nclass SourceStats(BaseModel):\n    name: str                    # 源名称\n    path: str                    # 源路径\n    recursive: bool              # 是否递归\n    n_files_indexed: int         # 已索引文件数\n    n_files_pending: int         # 待处理文件数\n    n_files_errored: int         # 错误文件数\n    last_scan_at: float | None   # 上次扫描时间\n    total_chunks: int            # 总分块数\n    disk_size_bytes: int         # 磁盘占用\n```\n\n### get_document\n\n获取完整文档内容。\n\n**函数签名：**\n\n```python\n@mcp.tool()\nasync def get_document(\n    path: Annotated[str, \"文档的绝对路径\"],\n    max_bytes: Annotated[int, \"最大读取字节数\"] = 1_000_000,\n) -> DocumentResponse\n```\n\n**返回类型（DocumentResponse）：**\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `path` | `str` | 文档绝对路径 |\n| `content` | `str` | 文件内容（可能截断） |\n| `file_type` | `str` | 标准化文件扩展名 |\n| `size_bytes` | `int` | 原始文件大小 |\n| `mtime` | `float` | 修改时间戳 |\n| `truncated` | `bool` | 是否被截断 |\n\n**异常处理：**\n\n- `DocumentNotFoundError`：路径不在任何配置的源中\n- `DocumentTooLargeError`：文件超过 `max_bytes`，返回开头 + 摘要\n\n资料来源：[src/memorymesh/core/models/search.py:45-70]()\n\n### summarize_source\n\n对指定源目录生成摘要信息，支持深度分析和要点提取。\n\n## 索引控制类工具\n\n### index_now\n\n强制重新索引指定路径。\n\n```python\n@mcp.tool()\nasync def index_now(\n    path: str,\n    recursive: bool = True,\n) -> IndexResponse\n```\n\n**约束条件：**\n\n- 路径必须在某个配置的源目录内\n- 返回处理统计：文件数、分块数、耗时\n\n### sync_source\n\n同步数据源，扫描新增、修改和删除的文件，更新索引。\n\n## 内存分层类工具\n\nMemoryMesh 支持内存分层（Memory Tiers），将分块分为 hot、warm、cold 层级，实现访问频率感知的存储优化。\n\n### 内存层级说明\n\n| 层级 | 说明 | 自动行为 |\n|------|------|----------|\n| **hot** | 热点数据，高频访问 | 手动固定或自动提升 |\n| **warm** | 温数据 | 定期维护时根据访问频率调整 |\n| **cold** | 冷数据 | 逐步降级，评分衰减 |\n\n### pin_memory / unpin_memory\n\n将分块固定到热层或解除固定。\n\n```python\n@mcp.tool()\ndef pin_memory(\n    chunk_id: Annotated[str, \"分块标识符，格式为 '<path>:<chunk_index>'\"],\n) -> dict:\n    \"\"\"固定分块到热层\"\"\"\n    return {\"chunk_id\": chunk_id, \"tier\": \"hot\", \"pinned\": True}\n\n@mcp.tool()\ndef unpin_memory(\n    chunk_id: Annotated[str, \"分块标识符，格式为 '<path>:<chunk_index>'\"],\n) -> dict:\n    \"\"\"解除固定，允许正常层级调整\"\"\"\n    return {\"chunk_id\": chunk_id, \"pinned\": False}\n```\n\n> 解除固定后，分块在下次维护运行前保留在热层，之后根据访问历史进行升降级。\n\n资料来源：[src/memorymesh/server/tools/pin_memory.py:1-60]()\n\n### forget_memory\n\n抑制或冷置分块，实现内容的渐进式遗忘。\n\n```python\n@mcp.tool()\ndef forget_memory(\n    chunk_id: Annotated[\n        str,\n        \"分块标识符，格式为 '<absolute_path>:<chunk_index>'\",\n    ],\n    mode: Annotated[\n        Literal[\"suppress\", \"cold\"],\n        \"'suppress': 立即隐藏; 'cold': 降级到冷层，评分逐渐衰减\"\n    ] = \"suppress\",\n) -> dict\n```\n\n**模式对比：**\n\n| 模式 | 行为 | 可逆性 |\n|------|------|--------|\n| `suppress` | 加入抑制列表，立即从搜索结果中隐藏 | 不可逆（需直接数据库访问） |\n| `cold` | 降级到冷层，评分逐渐衰减 | 可通过 `pin_memory` 恢复 |\n\n资料来源：[src/memorymesh/server/tools/forget_memory.py:1-50]()\n\n## 知识图谱类工具\n\n### graph_memory\n\n共现图查询工具，基于实体共现关系构建知识图谱。\n\n**典型用途：**\n\n- 发现概念间的关联\n- 探索特定实体类型的分布\n- 设定最小提及阈值过滤噪声\n\n**服务端缓存：** 图数据在服务器端缓存 60 秒，减少重复计算。\n\n### get_entity\n\n查询特定实体的详细信息，包括属性、关系和上下文。\n\n## 时间线类工具\n\n### query_timeline\n\n查询活动历史记录，包括索引操作、查询历史和变更事件。\n\n**审计日志字段：**\n\n| 字段 | 说明 |\n|------|------|\n| `ts` | 时间戳 |\n| `tool` | 调用的工具名称 |\n| `query_hash` | 查询的 SHA256 哈希（截断至 16 字符） |\n| `n_results` | 返回结果数 |\n| `latency_ms` | 延迟（毫秒） |\n| `client_id_if_known` | 客户端标识（已知时） |\n\n> **隐私保护**：审计日志不包含文档内容、chunk 内容或明文查询。\n\n## 工具调用流程\n\n```mermaid\nsequenceDiagram\n    participant Client as LLM 客户端\n    participant MCP as FastMCP 服务器\n    participant Engine as 搜索引擎\n    participant DB as 元数据存储\n    participant Ollama as Ollama LLM\n\n    Client->>MCP: search_memory(query, top_k)\n    MCP->>Engine: 混合检索\n    Engine->>DB: 查询向量 + BM25\n    DB-->>Engine: SearchHit 列表\n    Engine-->>MCP: SearchResponse\n    MCP-->>Client: hits + duration_ms\n\n    Client->>MCP: ask_memory(question)\n    MCP->>MCP: search_memory(question, top_k)\n    MCP->>Ollama: generate(RAG_prompt)\n    Ollama-->>MCP: answer\n    MCP-->>Client: AskMemoryResponse\n\n    Note over Client,DB: 写操作（index_now、pin_memory 等）\n    Client->>MCP: index_now(path)\n    MCP->>DB: 验证路径有效性\n    MCP->>Engine: 重新索引\n    Engine->>DB: 更新元数据\n    DB-->>MCP: IndexResponse\n    MCP-->>Client: 处理统计\n```\n\n## 访问控制与审计\n\n### 认证守卫\n\n工具注册时通过 `check_access(ctx, operation)` 检查访问权限：\n\n```python\nfrom memorymesh.server.auth_guard import check_access\n\nif (err := check_access(ctx, \"index\")) is not None:\n    return err\n```\n\n### 审计日志\n\n每次工具调用都会记录到 `~/.memorymesh/audit.jsonl`：\n\n```json\n{\"ts\": 1703001234.567, \"tool\": \"search_memory\", \"query_hash\": \"a1b2c3d4e5f6g7h8\", \"n_results\": 5, \"latency_ms\": 42.3}\n```\n\n## 配置与扩展\n\n### 配置来源优先级\n\n```python\n_DEFAULT_SEARCH_PATHS = [\n    Path.cwd() / \"config.yaml\",           # 1. 当前工作目录\n    Path.home() / \".memorymesh\" / \"config.yaml\",  # 2. 用户配置目录\n]\n```\n\n### 必需配置示例\n\n```yaml\nsources:\n  - name: documents\n    path: ~/Documents\n    recursive: true\n    extensions: [.txt, .md, .pdf]\n\nembeddings:\n  model: \"sentence-transformers/all-MiniLM-L6-v2\"\n\nollama:\n  enabled: true\n  model: \"llama2\"\n```\n\n## 错误处理规范\n\n| 错误类型 | 返回方式 | 说明 |\n|----------|----------|------|\n| 配置错误 | 抛出 `ConfigError` | YAML 解析或验证失败 |\n| 文档未找到 | 返回 `DocumentNotFoundError` | 路径不在任何源中 |\n| 文档过大 | 返回部分内容 + `DocumentTooLargeError` | 包含开头和摘要 |\n| Ollama 不可用 | 返回 `hint` | `ask_memory` 的容错机制 |\n| 访问被拒 | 返回错误字典 | `check_access` 拦截 |\n\n## 工具元数据速查\n\n| 工具名称 | 返回类型 | 异步 | LLM 依赖 |\n|----------|----------|------|----------|\n| `search_memory` | `SearchResponse` | ✅ | ❌ |\n| `ask_memory` | `AskMemoryResponse` | ✅ | Ollama |\n| `list_sources` | `SourcesReport` | ❌ | ❌ |\n| `get_document` | `DocumentResponse` | ✅ | ❌ |\n| `index_now` | `IndexResponse` | ✅ | ❌ |\n| `pin_memory` | `dict` | ❌ | ❌ |\n| `unpin_memory` | `dict` | ❌ | ❌ |\n| `forget_memory` | `dict` | ❌ | ❌ |\n| `graph_memory` | `dict` | ❌ | ❌ |\n| `get_entity` | `dict` | ❌ | ❌ |\n| `query_timeline` | `dict` | ❌ | ❌ |\n| `search_by_date` | `SearchResponse` | ❌ | ❌ |\n| `related_documents` | `list[SearchHit]` | ❌ | ❌ |\n| `summarize_source` | `dict` | ❌ | ❌ |\n| `sync_source` | `dict` | ❌ | ❌ |\n\n资料来源：[src/memorymesh/server/app.py:36-52]()\n\n---\n\n---\n\n## Doramagic 踩坑日志\n\n项目：kilhubprojects/memory-mesh\n\n摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。\n\n## 1. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | README/documentation is current enough for a first validation pass.\n\n## 2. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | last_activity_observed missing\n\n## 3. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | no_demo; severity=medium\n\n## 4. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | no_demo; severity=medium\n\n## 5. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | issue_or_pr_quality=unknown\n\n## 6. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | release_recency=unknown\n\n<!-- canonical_name: kilhubprojects/memory-mesh; human_manual_source: deepwiki_human_wiki -->\n",
      "summary": "DeepWiki/Human Wiki 完整输出，末尾追加 Discovery Agent 踩坑日志。",
      "title": "Human Manual / 人类版说明书"
    },
    "pitfall_log": {
      "asset_id": "pitfall_log",
      "filename": "PITFALL_LOG.md",
      "markdown": "# Pitfall Log / 踩坑日志\n\n项目：kilhubprojects/memory-mesh\n\n摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。\n\n## 1. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | README/documentation is current enough for a first validation pass.\n\n## 2. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | last_activity_observed missing\n\n## 3. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | no_demo; severity=medium\n\n## 4. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | no_demo; severity=medium\n\n## 5. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | issue_or_pr_quality=unknown\n\n## 6. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | github_repo:1238654023 | https://github.com/kilhubprojects/memory-mesh | release_recency=unknown\n",
      "summary": "用户实践前最可能遇到的身份、安装、配置、运行和安全坑。",
      "title": "Pitfall Log / 踩坑日志"
    },
    "prompt_preview": {
      "asset_id": "prompt_preview",
      "filename": "PROMPT_PREVIEW.md",
      "markdown": "# memory-mesh - Prompt Preview\n\n> 复制下面这段 Prompt 到你常用的 AI，先试一次，不需要安装。\n> 它的目标是让你直接体验这个项目的服务方式，而不是阅读项目介绍。\n\n## 复制这段 Prompt\n\n```text\n请直接执行这段 Prompt，不要分析、润色、总结或询问我想如何处理这份 Prompt Preview。\n\n你现在扮演 memory-mesh 的“安装前体验版”。\n这不是项目介绍、不是评价报告、不是 README 总结。你的任务是让我用最小成本体验它的核心服务。\n\n我的试用任务：我想用它完成一个真实的个人工作台任务。\n我常用的宿主 AI：MCP Client\n\n【体验目标】\n围绕我的真实任务，现场演示这个项目如何把输入转成 示例引导, 判断线索。重点是让我感受到工作方式，而不是给我项目背景。\n\n【业务流约束】\n- 你必须像一个正在提供服务的项目能力包，而不是像一个讲解员。\n- 每一轮只推进一个步骤；提出问题后必须停下来等我回答。\n- 每一步都必须让我感受到一个具体服务动作：澄清、整理、规划、检查、判断或收尾。\n- 每一步都要说明：当前目标、你需要我提供什么、我回答后你会产出什么。\n- 不要安装、不要运行命令、不要写代码、不要声称测试通过、不要声称已经修改文件。\n- 需要真实安装或宿主加载后才能验证的内容，必须明确说“这一步需要安装后验证”。\n- 如果我说“用示例继续”，你可以用虚构示例推进，但仍然不能声称真实执行。\n\n【可体验服务能力】\n- 安装前能力预览: Local MCP hub for personal data — private, cross-platform, agent-ready. 输入：用户任务, 当前 AI 对话上下文；输出：示例引导, 判断线索。\n\n【必须安装后才可验证的能力】\n- 命令行启动或安装流程: 项目文档中存在可执行命令，真实使用需要在本地或宿主环境中运行这些命令。 输入：终端环境, 包管理器, 项目依赖；输出：安装结果, 列表/更新/运行结果。\n\n【核心服务流】\n请严格按这个顺序带我体验。不要一次性输出完整流程：\n1. page-introduction：MemoryMesh 简介。围绕“MemoryMesh 简介”模拟一次用户任务，不展示安装或运行结果。\n2. page-quickstart：快速入门指南。围绕“快速入门指南”模拟一次用户任务，不展示安装或运行结果。\n3. page-architecture：系统架构。围绕“系统架构”模拟一次用户任务，不展示安装或运行结果。\n4. page-indexing-pipeline：索引管道。围绕“索引管道”模拟一次用户任务，不展示安装或运行结果。\n5. page-search-engine：搜索引擎。围绕“搜索引擎”模拟一次用户任务，不展示安装或运行结果。\n\n【核心能力体验剧本】\n每一步都必须按“输入 -> 服务动作 -> 中间产物”执行。不要只说流程名：\n1. page-introduction\n输入：用户提供的“MemoryMesh 简介”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n2. page-quickstart\n输入：用户提供的“快速入门指南”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n3. page-architecture\n输入：用户提供的“系统架构”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n4. page-indexing-pipeline\n输入：用户提供的“索引管道”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n5. page-search-engine\n输入：用户提供的“搜索引擎”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n【项目服务规则】\n这些规则决定你如何服务用户。不要解释规则本身，而要在每一步执行时遵守：\n- 先确认用户任务、输入材料和成功标准，再模拟项目能力。\n- 每一步都必须形成可检查的小产物，并等待用户确认后再继续。\n- 凡是需要安装、调用工具或访问外部服务的能力，都必须标记为安装后验证。\n\n【每一步的服务约束】\n- Step 1 / page-introduction：Step 1 必须围绕“MemoryMesh 简介”形成一个小中间产物，并等待用户确认。\n- Step 2 / page-quickstart：Step 2 必须围绕“快速入门指南”形成一个小中间产物，并等待用户确认。\n- Step 3 / page-architecture：Step 3 必须围绕“系统架构”形成一个小中间产物，并等待用户确认。\n- Step 4 / page-indexing-pipeline：Step 4 必须围绕“索引管道”形成一个小中间产物，并等待用户确认。\n- Step 5 / page-search-engine：Step 5 必须围绕“搜索引擎”形成一个小中间产物，并等待用户确认。\n\n【边界与风险】\n- 不要声称已经安装、运行、调用 API、读写本地文件或完成真实任务。\n- 安装前预览只能展示工作方式，不能证明兼容性、性能或输出质量。\n- 涉及安装、插件加载、工具调用或外部服务的能力必须安装后验证。\n\n【可追溯依据】\n这些路径只用于你内部校验或在我追问“依据是什么”时简要引用。不要在首次回复主动展开：\n- https://github.com/kilhubprojects/memory-mesh\n- https://github.com/kilhubprojects/memory-mesh#readme\n- README.md\n- ROADMAP.md\n- config.example.yaml\n- src/memorymesh/cli.py\n- ARCHITECTURE.md\n- src/memorymesh/server/app.py\n- src/memorymesh/server/transports.py\n- src/memorymesh/indexer/file_indexer.py\n- src/memorymesh/indexer/watcher.py\n- src/memorymesh/parsing/registry.py\n\n【首次问题规则】\n- 首次三问必须先确认用户目标、成功标准和边界，不要提前进入工具、安装或实现细节。\n- 如果后续需要技术条件、文件路径或运行环境，必须等用户确认目标后再追问。\n\n首次回复必须只输出下面 4 个部分：\n1. 体验开始：用 1 句话说明你将带我体验 memory-mesh 的核心服务。\n2. 当前步骤：明确进入 Step 1，并说明这一步要解决什么。\n3. 你会如何服务我：说明你会先改变我完成任务的哪个动作。\n4. 只问我 3 个问题，然后停下等待回答。\n\n首次回复禁止输出：后续完整流程、证据清单、安装命令、项目评价、营销文案、已经安装或运行的说法。\n\nStep 1 / brainstorming 的二轮协议：\n- 我回答首次三问后，你仍然停留在 Step 1 / brainstorming，不要进入 Step 2。\n- 第二次回复必须产出 6 个部分：澄清后的任务定义、成功标准、边界条件、\n  2-3 个可选方案、每个方案的权衡、推荐方案。\n- 第二次回复最后必须问我是否确认推荐方案；只有我明确确认后，才能进入下一步。\n- 第二次回复禁止输出 git worktree、代码计划、测试文件、命令或真实执行结果。\n\n后续对话规则：\n- 我回答后，你先完成当前步骤的中间产物并等待确认；只有我确认后，才能进入下一步。\n- 每一步都要生成一个小的中间产物，例如澄清后的目标、计划草案、测试意图、验证清单或继续/停止判断。\n- 所有演示都写成“我会建议/我会引导/这一步会形成”，不要写成已经真实执行。\n- 不要声称已经测试通过、文件已修改、命令已运行或结果已产生。\n- 如果某个能力必须安装后验证，请直接说“这一步需要安装后验证”。\n- 如果证据不足，请明确说“证据不足”，不要补事实。\n```\n",
      "summary": "不安装项目也能感受能力节奏的安全试用 Prompt。",
      "title": "Prompt Preview / 安装前试用 Prompt"
    },
    "quick_start": {
      "asset_id": "quick_start",
      "filename": "QUICK_START.md",
      "markdown": "# Quick Start / 官方入口\n\n项目：kilhubprojects/memory-mesh\n\n## 官方安装入口\n\n### Python / pip · 官方安装入口\n\n```bash\npip install memorymesh-mcp\n```\n\n来源：https://github.com/kilhubprojects/memory-mesh#readme\n\n## 来源\n\n- repo: https://github.com/kilhubprojects/memory-mesh\n- docs: https://github.com/kilhubprojects/memory-mesh#readme\n",
      "summary": "从项目官方 README 或安装文档提取的开工入口。",
      "title": "Quick Start / 官方入口"
    }
  },
  "validation_id": "dval_98373f49976e4783a115210e0517567c"
}
