news 2026/9/1 9:55:36

基于DeepSeek Harness构建Obsidian智能助手:从零开发AI知识管理Agent

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于DeepSeek Harness构建Obsidian智能助手:从零开发AI知识管理Agent

1. 先搞清楚 DeepSeek Harness 和 Obsidian 结合能解决什么问题

如果你在用 Obsidian 做笔记,并且希望笔记库能“活”起来,比如自动帮你整理、总结、关联信息,甚至基于你的笔记内容回答你的问题,那么 DeepSeek Harness 就是一个值得关注的方案。它不是一个现成的 Obsidian 插件,而是一个让你能基于 DeepSeek 这类大语言模型,为你的 Obsidian 知识库开发专属 AI 助手的开发框架。

简单来说,它的核心价值是:让你能用一个相对标准化的方式,把大模型的能力“注入”到你的 Obsidian 库中,打造一个真正理解你个人知识体系的智能体(Agent)。这和你直接用网页版或 API 调用大模型聊天完全不同。一个专属 Agent 能持续地、有上下文地处理你的笔记,比如你问“我上个月关于项目架构的思考有哪些?”,它能从你的笔记里找到相关段落并总结,而不是给你一个通用的、脱离你个人语境的回答。

很多人看到“Agent开发”就觉得门槛很高,但 DeepSeek Harness 试图降低这个门槛。它提供了一套工具链,帮你处理与大模型 API 的通信、上下文管理、工具调用(比如读取文件、搜索笔记)等底层工作。你的重点可以放在设计这个 Agent 应该具备哪些“技能”上,比如“总结每日笔记”、“根据标签生成知识图谱”、“自动为新建笔记推荐关联链接”。

所以,这篇文章适合两类人:一是 Obsidian 的重度用户,希望提升知识管理的自动化水平;二是对 AI Agent 开发感兴趣,想找一个具体、有个人价值的场景来练手的开发者。最关键的,这不是一个“一键安装”的魔法,而是一个需要你动手配置和定义的开发过程,但回报是一个完全为你服务的私人知识 AI。

2. 动手前的环境准备与核心概念梳理

在开始写代码之前,你得把环境和概念理清楚。这里没有一键安装包,你需要自己搭建一个开发环境。

2.1 核心组件与它们的关系

  1. Obsidian:你的知识库本体,一个由 Markdown 文件组成的文件夹。Agent 最终要操作的就是这个文件夹里的内容。
  2. DeepSeek API:提供大模型能力的大脑。你需要一个 DeepSeek 的 API Key。目前(根据常见实践)你可以通过官方平台申请。这是调用模型进行理解、推理和生成的凭证。
  3. DeepSeek Harness:这是关键。它不是 DeepSeek 模型本身,而是一个开发框架或 SDK。你可以把它理解为一套脚手架和工具箱,它帮你:
    • 用代码定义 Agent 的行为(角色设定、可用工具)。
    • 方便地调用 DeepSeek API。
    • 管理对话历史和多轮交互的上下文。
    • 集成外部工具(比如文件读写、网络搜索——但网络搜索功能需合规使用)。
  4. 你的 Agent 程序:这是你用 DeepSeek Harness 框架编写的一个独立应用程序。这个程序会运行在你的电脑或服务器上,它通过 Harness 与 DeepSeek API 对话,并根据你的指令去读取、写入或分析你的 Obsidian 库文件夹。

它们的工作流程是:你的 Agent 程序启动 -> 通过 Harness 向 DeepSeek API 发送请求和你的笔记上下文 -> 模型返回思考结果和行动指令 -> Agent 程序通过 Harness 执行指令(如读取某个笔记文件)-> 将结果再次发送给模型 -> 循环直至任务完成,最后将结果输出给你或写入笔记。

2.2 本地开发环境搭建

你需要准备以下环境,我建议按这个顺序检查:

  1. Python 环境:DeepSeek Harness 通常是一个 Python 库。确保你的系统安装了 Python(建议 3.8 以上版本)。打开终端,输入python --versionpython3 --version确认。
  2. 安装 DeepSeek Harness:在终端里,使用 pip 安装。命令通常类似于:
    pip install deepseek-harness
    如果遇到网络问题,可以考虑使用国内镜像源,例如:
    pip install deepseek-harness -i https://pypi.tuna.tsinghua.edu.cn/simple
    安装后,可以通过pip show deepseek-harness查看版本信息,确认安装成功。
  3. 获取 DeepSeek API Key:访问 DeepSeek 官方平台(通常在其官网能找到开发者或 API 相关入口),注册并获取你的 API Key。妥善保管这个 Key,不要把它直接硬编码在提交到公开仓库的代码里。
  4. 准备你的 Obsidian 库:明确你的 Obsidian 仓库在本地磁盘上的绝对路径。例如:/Users/YourName/Documents/MyObsidianVaultD:\Notes\MyVault。确保你的 Agent 程序有权限读取和写入这个目录。

3. 从零构建你的第一个 Obsidian 问答 Agent

现在,我们从一个最简单的功能开始:创建一个能回答关于你笔记内容的 Agent。这个 Agent 将具备“读取指定笔记文件”的能力。

3.1 项目初始化与依赖管理

首先,创建一个新的项目目录,并初始化一个 Python 虚拟环境,这是为了隔离项目依赖,避免包版本冲突。

mkdir obsidian-agent && cd obsidian-agent python -m venv venv # 激活虚拟环境 # 在 Windows 上: venv\Scripts\activate # 在 macOS/Linux 上: source venv/bin/activate

激活虚拟环境后,再次安装deepseek-harness。然后,我们创建一个requirements.txt文件来记录依赖,虽然现在只有一个,但这是个好习惯。

echo “deepseek-harness” > requirements.txt

3.2 编写核心 Agent 逻辑

创建一个名为obsidian_qa_agent.py的文件。我们将一步步构建它。

第一步:导入必要的模块并设置 API Key

import os from harness import Agent, Tool from harness.tools import FunctionTool from typing import Any # 从环境变量中读取 API Key,这是更安全的做法 DEEPSEEK_API_KEY = os.getenv(“DEEPSEEK_API_KEY”) if not DEEPSEEK_API_KEY: # 如果环境变量没有设置,可以在这里临时设置(仅用于测试,生产环境务必用环境变量) print(“警告:未设置 DEEPSEEK_API_KEY 环境变量”) DEEPSEEK_API_KEY = “your_api_key_here” # 替换成你的真实 Key # 设置你的 Obsidian 库路径 OBSIDIAN_VAULT_PATH = “/path/to/your/obsidian/vault” # 务必替换成你的实际路径

第二步:创建“读取笔记”工具

Agent 需要通过“工具”来与世界交互。我们首先定义一个能读取 Obsidian 笔记文件的工具。

def read_obsidian_note(note_name: str) -> str: “”” 读取 Obsidian 库中的指定笔记文件。 Args: note_name: 笔记文件名(如 ‘项目规划.md’),或相对路径。 Returns: 笔记的文本内容。 “”” # 构建完整的文件路径 note_path = os.path.join(OBSIDIAN_VAULT_PATH, note_name) # 确保文件存在 if not os.path.exists(note_path): return f“错误:未找到笔记文件 ‘{note_name}’。请检查文件名和路径。” try: with open(note_path, ‘r’, encoding=‘utf-8’) as f: content = f.read() return content except Exception as e: return f“读取笔记时发生错误:{str(e)}” # 将函数包装成 Harness 能识别的 Tool 对象 read_note_tool = FunctionTool( func=read_obsidian_note, name=“read_obsidian_note”, description=“读取指定名称的 Obsidian 笔记文件内容。输入应为笔记的文件名(例如 ‘日记-2024-05-01.md’)。“ )

第三步:配置并启动 Agent

现在,我们使用 Harness 来创建 Agent 实例,赋予它工具,并定义它的角色。

def main(): # 1. 创建 Agent,指定使用的模型和 API Key agent = Agent( model=“deepseek-chat”, # 指定 DeepSeek 模型 api_key=DEEPSEEK_API_KEY, system_message=“””你是一个专用于处理 Obsidian 知识库的助手。你可以读取用户指定的笔记文件,并基于笔记内容回答用户的问题。 当用户询问笔记内容时,你应该主动使用 ‘read_obsidian_note’ 工具来获取准确信息,然后进行总结或回答。 如果用户的问题无法通过现有笔记内容回答,请如实告知。“””, tools=[read_note_tool], # 赋予 Agent 工具 ) print(“Obsidian QA Agent 已启动。输入 ‘quit’ 或 ‘exit’ 退出。”) print(f“我的知识库位于:{OBSIDIAN_VAULT_PATH}”) print(“-” * 50) # 2. 简单的对话循环 while True: try: user_input = input(“\n你问: “).strip() if user_input.lower() in [‘quit’, ‘exit’, ‘q’]: print(“再见!”) break if not user_input: continue # 3. 将用户输入发送给 Agent response = agent.run(user_input) # 4. 打印 Agent 的回复 print(f“\n助手: {response}”) except KeyboardInterrupt: print(“\n程序被中断。”) break except Exception as e: print(f“\n运行出错:{e}”) if __name__ == “__main__”: main()

3.3 运行与测试你的第一个 Agent

  1. 将代码中的OBSIDIAN_VAULT_PATHDEEPSEEK_API_KEY(如果没用环境变量)替换成你的真实信息。
  2. 在终端中,确保位于项目目录且虚拟环境已激活,运行:
    python obsidian_qa_agent.py
  3. 如果一切正常,你会看到启动提示。现在你可以尝试问它关于你笔记的问题。例如:
    • “读取名为 ‘项目规划.md’ 的笔记。”
    • “我有一篇叫 ‘读书笔记-深度工作.md’ 的笔记,里面主要讲了什么观点?”
    • “帮我总结一下 ‘会议记录-20240510.md’ 的要点。”

关键点验证

  • 启动成功:程序不报错,能打印出提示信息。
  • 工具调用:当你问及具体笔记时,观察 Agent 的回复。它应该会显示它“使用”了read_obsidian_note工具,然后给出基于文件内容的回答。你可以在代码中添加打印日志,来更清晰地看到工具被调用的过程。
  • 内容准确:核对 Agent 总结的内容是否与你笔记原文一致。

如果遇到ModuleNotFoundError,检查deepseek-harness是否安装正确。如果遇到 API 认证错误,检查 API Key 是否正确且有效。如果工具调用失败,检查文件路径和权限。

4. 扩展 Agent 能力:从问答到自动整理

一个只会读文件的 Agent 只是开始。真正的价值在于让它能主动帮你管理知识库。下面我们为它添加“写笔记”和“搜索笔记”两个核心能力。

4.1 添加“创建/编辑笔记”工具

read_obsidian_note工具后面,继续添加以下函数和工具:

def write_obsidian_note(note_name: str, content: str, mode: str = ‘append’) -> str: “”” 向 Obsidian 库中写入或追加内容。 Args: note_name: 笔记文件名。 content: 要写入的内容。 mode: ‘write’ 为覆盖写入,’append’ 为追加到文件末尾。 Returns: 操作结果描述。 “”” note_path = os.path.join(OBSIDIAN_VAULT_PATH, note_name) try: if mode == ‘write’: with open(note_path, ‘w’, encoding=‘utf-8’) as f: f.write(content) action = “已覆盖写入” elif mode == ‘append’: with open(note_path, ‘a’, encoding=‘utf-8’) as f: f.write(‘\n\n’ + content) # 追加时增加空行分隔 action = “已追加内容” else: return “错误:模式参数错误,应为 ‘write’ 或 ‘append’。” return f“成功:{action}到笔记 ‘{note_name}’。” except Exception as e: return f“写入笔记时发生错误:{str(e)}” write_note_tool = FunctionTool( func=write_obsidian_note, name=“write_obsidian_note”, description=“创建或修改 Obsidian 笔记。需要提供笔记文件名、要写入的内容,以及模式(’write’ 覆盖或 ‘append’ 追加)。“ )

4.2 添加“搜索笔记”工具

仅仅按文件名读取不够,我们还需要能根据内容搜索。这里实现一个简单的本地文件内容搜索:

def search_obsidian_notes(keyword: str, max_results: int = 5) -> str: “”” 在 Obsidian 库中搜索包含关键词的笔记。 Args: keyword: 搜索关键词。 max_results: 返回的最大结果数量。 Returns: 搜索结果摘要。 “”” results = [] keyword_lower = keyword.lower() # 遍历库中所有 .md 文件 for root, dirs, files in os.walk(OBSIDIAN_VAULT_PATH): for file in files: if file.endswith(‘.md’): file_path = os.path.join(root, file) try: with open(file_path, ‘r’, encoding=‘utf-8’) as f: text = f.read() if keyword_lower in text.lower(): # 计算相对路径,便于用户识别 rel_path = os.path.relpath(file_path, OBSIDIAN_VAULT_PATH) # 简单截取包含关键词的上下文 idx = text.lower().find(keyword_lower) snippet_start = max(0, idx - 50) snippet_end = min(len(text), idx + len(keyword) + 50) snippet = text[snippet_start:snippet_end].replace(‘\n’, ‘ ‘) results.append(f“- {rel_path}: …{snippet}…”) if len(results) >= max_results: break except: continue if len(results) >= max_results: break if results: return f“找到 {len(results)} 条包含 ‘{keyword}’ 的笔记:\n” + “\n”.join(results) else: return f“未找到包含 ‘{keyword}’ 的笔记。”

4.3 更新 Agent 配置并测试复杂任务

现在,更新创建Agent的代码,将新工具也加进去:

agent = Agent( model=“deepseek-chat”, api_key=DEEPSEEK_API_KEY, system_message=“””你是一个功能强大的 Obsidian 知识库管理助手。你可以: 1. 读取指定笔记的内容。 2. 根据内容搜索相关的笔记。 3. 创建新的笔记或向现有笔记添加内容。 请根据用户的需求,灵活使用这些工具来完成任务。在修改笔记前,如果内容不确定,可以先与用户确认。“””, tools=[read_note_tool, write_note_tool, search_obsidian_notes_tool], # 包含所有工具 )

重启你的 Agent 程序,现在你可以尝试更复杂的指令:

  • 场景一:信息整合

    • 你:“搜索所有提到‘深度学习’的笔记。”
    • Agent 会调用搜索工具,返回结果列表。
    • 你:“读取‘深度学习入门.md’这篇笔记,然后把它的核心概念总结出来,追加到名为‘知识总结.md’的笔记里。”
    • Agent 会先调用读取工具获取内容,让模型总结,再调用写入工具进行追加。
  • 场景二:每日日志

    • 你:“创建一篇名为‘日志-2024-05-20.md’的笔记,内容是我的今日待办:1. 完成Agent测试;2. 写项目报告。”
    • Agent 会直接调用写入工具创建新文件。

关键点:观察 Agent 的“思考过程”。一个好的 Agent 框架(如 Harness)会允许模型进行“链式思考”,即先决定用什么工具,使用工具拿到结果后,再基于结果进行下一步推理或行动。你的程序日志应该能反映出这个“使用工具A -> 获取结果 -> 使用工具B”的过程。

5. 生产化考量:安全、稳定与性能

一个在命令行里跑起来的 Demo 和能稳定、安全使用的工具之间还有距离。如果你打算长期使用这个 Agent,以下几个点必须考虑。

5.1 安全性加固

  1. API Key 管理:绝对不要将 API Key 硬编码在代码中。必须使用环境变量或安全的配置管理工具(如python-dotenv读取.env文件)。
    # .env 文件 DEEPSEEK_API_KEY=sk-your-actual-key-here OBSIDIAN_VAULT_PATH=/path/to/vault
    # 在代码中读取 from dotenv import load_dotenv load_dotenv() DEEPSEEK_API_KEY = os.getenv(“DEEPSEEK_API_KEY”)
  2. 文件操作权限:确保 Agent 程序只有对你 Obsidian 库的必要读写权限,不要以过高系统权限运行。可以考虑在工具函数中加入路径安全检查,防止恶意指令尝试读写库外部的系统文件(路径遍历攻击)。
    def safe_join(base_path, target_path): “””防止路径遍历攻击的安全连接函数“”” final_path = os.path.normpath(os.path.join(base_path, target_path)) if not final_path.startswith(os.path.normpath(base_path)): raise ValueError(“非法路径访问!”) return final_path
  3. 操作确认:对于“写入”或“删除”这类破坏性操作,可以在工具函数中设计一个“模拟”模式,或者要求用户在关键操作前进行二次确认。更高级的做法是让 Agent 在执行前,将其计划的操作以自然语言描述给用户确认。

5.2 稳定性与错误处理

  1. 网络与 API 容错:DeepSeek API 调用可能因网络或服务端问题失败。你的代码需要包含重试机制和友好的错误提示。
    import time from tenacity import retry, stop_after_attempt, wait_exponential @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10)) def robust_agent_run(agent, query): try: return agent.run(query) except Exception as e: # 记录日志 print(f“API 调用失败:{e}”) # 根据错误类型决定是重试还是返回用户友好信息 if “rate limit” in str(e).lower(): return “请求过于频繁,请稍后再试。” else: return “服务暂时不可用,请检查网络或稍后重试。”
  2. 上下文长度管理:大模型有上下文窗口限制。如果你的笔记内容很长,或者对话历史很多,需要设计策略。比如,让read_note_tool只读取文件的前 N 个字符,或者使用更高级的“检索增强生成(RAG)”技术,先搜索出相关片段再喂给模型,而不是整个文件。
  3. 日志记录:为你的 Agent 添加详细的日志记录,记录每一次用户查询、工具调用、API 请求和结果。这对于调试和了解 Agent 的行为模式至关重要。可以使用 Python 标准的logging模块。

5.3 性能与用户体验优化

  1. 异步处理:如果任务耗时较长(如搜索整个库),可以考虑使用异步编程(asyncio)来避免阻塞主线程,保持交互响应。
  2. 构建图形界面(GUI)或集成到 Obsidian:命令行工具对大多数用户不友好。你可以:
    • 使用tkinterPyQtStreamlit快速构建一个简单的桌面或 Web 界面。
    • 更优雅的方案:开发一个真正的 Obsidian 插件。Obsidian 插件使用 TypeScript/JavaScript 开发。你的 Python Agent 可以作为一个本地后端服务运行,Obsidian 插件通过 HTTP 请求与它通信。这样就能在 Obsidian 内部直接调用你的 AI 助手。
  3. 工具的精炼与扩展:根据你的使用场景,不断优化和增加工具。例如:
    • analyze_daily_notes_tool: 分析过去一周的日记,生成周报。
    • find_unlinked_mentions_tool: 查找笔记中提及但未创建链接的术语。
    • generate_mind_map_tool: 根据笔记内容,生成 Mermaid 思维导图代码。

6. 常见问题排查与调试思路

开发过程中,你肯定会遇到各种问题。别急着修改核心逻辑,按照这个顺序排查,能解决大部分情况。

6.1 Agent 不调用工具,只会空泛回答

  • 检查系统提示词system_message是否清晰定义了 Agent 的角色并明确鼓励它使用工具?像“你应该主动使用工具”、“你可以使用以下工具”这样的指令很重要。
  • 检查工具描述FunctionTool中的description字段是否清晰、准确?模型依赖这个描述来决定是否以及何时调用工具。描述应说明工具的用途、输入参数的意义。
  • 检查模型能力:确认你使用的model参数(如deepseek-chat)是否支持工具调用功能。查阅 DeepSeek 最新的 API 文档。
  • 简化测试:用一个极其明确、必须用工具才能完成的指令测试,如“请精确地读取文件‘test.md’的第一行并告诉我。”,观察日志。

6.2 工具调用失败或结果不对

  • 路径问题:这是最常见的问题。打印出工具函数内部拼接的完整路径note_path,确认它是否指向了真实存在的文件。注意相对路径和绝对路径,以及操作系统间的路径分隔符差异(/vs\)。
  • 文件编码:确保读写文件时指定了encoding=‘utf-8’。Obsidian 笔记默认是 UTF-8,但某些系统可能不同。
  • 权限问题:运行 Agent 程序的用户是否有权读取和写入目标 Obsidian 目录?
  • 函数签名:确保FunctionTool包装的函数,其参数名和类型与描述匹配。工具调用时,模型会尝试生成一个 JSON 对象来匹配这些参数。

6.3 API 调用返回错误

  • 认证失败:检查 API Key 是否正确、是否已设置环境变量、Key 是否有余额或是否过期。
  • 速率限制:免费或低阶 API 套餐可能有每分钟/每天的调用次数限制。错误信息中通常会包含rate limit。你需要增加请求间隔或升级套餐。
  • 网络超时:检查你的网络连接,考虑在代码中增加请求超时设置和重试逻辑。
  • 模型不可用:确认model参数值是否为当前 API 支持的有效模型名称。

6.4 程序运行缓慢

  • 搜索工具效率os.walk遍历整个库在笔记很多时会很慢。考虑:
    1. 为笔记库建立索引(例如,将笔记标题和摘要存入一个 SQLite 数据库)。
    2. 使用专门的本地搜索引擎库,如whooshtantivy
    3. 限制搜索的目录深度或文件类型。
  • 上下文过长:如果每次对话都将很长的笔记内容或历史记录发送给 API,会导致请求变慢且消耗更多 Token。实施上文提到的上下文管理策略。
  • 同步调用:如果未来集成了 GUI,确保耗时的 API 调用或文件搜索在后台线程中进行,避免界面卡死。

7. 超越 Demo:将 Agent 融入你的工作流

Demo 跑通只是第一步。要让这个 Agent 产生持续价值,你需要把它变成你工作流的一部分。

思路一:自动化定期任务写一个脚本,让 Agent 在每天固定时间(例如,早上 9 点)自动运行。任务可以是:

  • 扫描昨日新增或修改的笔记,生成一个摘要发送到你的邮箱。
  • 检查“待办事项”笔记,将过期的任务标记出来。
  • 在所有笔记中寻找新的、未建立链接的关联,并提示你。

这可以通过系统的定时任务(如 Linux 的cron,Windows 的“任务计划程序”)来实现。

思路二:作为创意写作伙伴当你写一篇新文章或报告时,可以启动 Agent,将你的草稿和大纲喂给它,让它:

  • 根据你过往的笔记,提供相关的案例或数据。
  • 检查逻辑连贯性。
  • 甚至帮你润色某些段落。

思路三:构建知识问答系统将你的 Obsidian 库视为一个私有知识库,利用 Agent 的搜索和读取能力,搭建一个简单的问答接口。你可以通过一个简单的 Web 页面(用 Flask 或 FastAPI 快速搭建)来提问,Agent 在后台查找并生成答案。

最重要的建议:不要一开始就追求功能大而全。从一个你最痛点的场景开始(比如“每周帮我整理周报”),把这个场景下的 Agent 做到稳定、好用。然后再基于这个基础,逐步扩展它的能力。在这个过程中,你会更深刻地理解 Agent 的潜力与局限,从而打造出真正为你所用的 Obsidian 专属智能助手。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 9:55:08

大模型多轮训练实战:从SFT到强化学习的迭代优化方法

最近这个本地大模型算法项目走到了一个比较关键的节点:整体进度大约 90%。项目内部最核心的手段不是继续堆参数、刷榜单,而是用多轮训练把模型能力一层一层拉起来。如果你正在做 SFT、偏好对齐、强化学习微调,或者准备把一套只能跑 demo 的模…

作者头像 李华
网站建设 2026/9/1 9:48:57

WeChat本地数据库深度解析:WeFlow破解的加密盒子就藏在你电脑里

WeChat本地数据库深度解析:WeFlow破解的加密盒子就藏在你电脑里 【免费下载链接】WeFlow WeFlow - 一个本地的微信聊天记录导出和年度报告应用 项目地址: https://gitcode.com/gh_mirrors/wefl/WeFlow 你的微信聊天记录,其实一直躺在自己电脑的硬…

作者头像 李华
网站建设 2026/9/1 9:45:41

Semantica Datalog推理深度解析:递归规则与传递关系实战

Semantica Datalog推理深度解析:递归规则与传递关系实战 【免费下载链接】semantica Graph-Native Infrastructure for Context and Accountable AI Systems 项目地址: https://gitcode.com/GitHub_Trending/sema/semantica Semantica 是一个面向知识图谱的图…

作者头像 李华
网站建设 2026/9/1 9:45:28

DESIGN.md pre-commit钩子实战:让坏设计令牌提交不了仓库

DESIGN.md pre-commit钩子实战:让坏设计令牌提交不了仓库 【免费下载链接】design.md A format specification for describing a visual identity to coding agents. DESIGN.md gives agents a persistent, structured understanding of a design system. 项目地址…

作者头像 李华