From 1fe1d2a130cdd4d20a2421c08dd0175fa48ee54b Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 1 Oct 2026 22:42:04 +0800 Subject: [PATCH] =?UTF-8?q?chore(wiki):=20=E6=96=B0=E5=A2=9E=20MergeWiki.p?= =?UTF-8?q?y=20=E5=BF=AB=E9=80=9F=E5=90=88=E5=B9=B6=20wiki=20=E4=BE=9B=20A?= =?UTF-8?q?I=20=E5=88=86=E6=9E=90=EF=BC=88=E5=90=AB=E5=BC=B1=E6=97=B6?= =?UTF-8?q?=E6=95=88=E6=80=A7=E5=A3=B0=E6=98=8E=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + MergeWiki.py | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 .gitignore create mode 100644 MergeWiki.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c83fe95 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# MergeWiki.py 生成的 AI 快照(弱时效性,不入库) +WikiAi*.md diff --git a/MergeWiki.py b/MergeWiki.py new file mode 100644 index 0000000..a523165 --- /dev/null +++ b/MergeWiki.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +"""MergeWiki.py - 把 wiki 目录下的 Markdown 快速合并成可发送给 AI 的快照 + +用法(在本目录下执行): + python MergeWiki.py # → WikiAi0.md(若超块大小则 WikiAi0.md, WikiAi1.md, ...) + python MergeWiki.py 输出前缀 # 自定义输出前缀 + python MergeWiki.py 输出前缀 200 # 自定义输出前缀 + 每块大小(KB) + +特点: + * 递归收集本目录(脚本所在目录)下所有 *.md / *.MD(跳过 .git 与自身产出); + * 按路径排序合并,结果可复现; + * 每个文件前后插入 `` 边界标记; + * 每块开头插入文件头,含用途与【弱时效性】声明; + * 默认每块 199KB(与 Tools/sendaiandsplit.py 口径一致)。 + +【弱时效性声明】 + wiki 会持续修订,本脚本产出的是**生成时刻的快照**。发送给 AI 前请重新生成, + 分析结论请以 wiki 目录下的**实时文件**为准,不要固化。 +""" +import os +import sys +import time + +DEFAULT_PREFIX = "WikiAi" +DEFAULT_CHUNK_KB = 199 + +HERE = os.path.dirname(os.path.abspath(__file__)) + + +def CollectMarkdown(Dir: str, Prefix: str): + """递归收集 *.md / *.MD(跳过 .git 与以 Prefix 开头的自身产出),返回排序后的路径列表。""" + Matched = [] + LowPrefix = Prefix.lower() + for Root, Dirs, Files in os.walk(Dir): + Dirs[:] = [d for d in Dirs if d != ".git"] + for F in Files: + Lower = F.lower() + if not (Lower.endswith(".md")): + continue + if Lower.startswith(LowPrefix): + continue + Matched.append(os.path.join(Root, F)) + Matched.sort() + return Matched + + +def Banner(Title: str, SrcDir: str, FileCount: int, Total: int, + ChunkIndex: int, ChunkTotal: int, OutName: str) -> str: + """生成面向 AI 分析的文件头(含【弱时效性】声明)。""" + Stamp = time.strftime("%Y-%m-%d %H:%M:%S") + return ( + "\n" + f"\n" + "\n" + "\n" + "\n" + f"\n" + f"\n" + f"\n" + f"\n" + f"\n" + "\n\n" + ) + + +def MergeWiki(Dir: str, Prefix: str, ChunkKb: int) -> int: + """合并 Dir 下所有 Markdown,带边界标记与【弱时效性】文件头,按 ChunkKb 分块输出。""" + if not os.path.isdir(Dir): + print(f"错误: 目录 {Dir} 不存在", file=sys.stderr) + return 1 + + Matched = CollectMarkdown(Dir, Prefix) + if not Matched: + print(f"错误: {Dir} 下没有可合并的 Markdown", file=sys.stderr) + return 1 + + Parts = [] + Total = 0 + try: + for Path in Matched: + Rel = os.path.relpath(Path, Dir).replace("\\", "/") + with open(Path, "r", encoding="utf-8") as Fh: + Content = Fh.read() + Total += len(Content) + Parts.append(f"\n") + Parts.append(Content) + if not Content.endswith("\n"): + Parts.append("\n") + Parts.append(f"\n\n") + except OSError as Exc: + print(f"错误: 读取源文件失败: {Exc}", file=sys.stderr) + return 1 + + Body = "".join(Parts) + ChunkSize = max(1, ChunkKb) * 1024 + ChunkTotal = max(1, (len(Body) + ChunkSize - 1) // ChunkSize) + Title = "Viper wiki 快照(AI 分析用)" + + for i in range(ChunkTotal): + Chunk = Body[i * ChunkSize:(i + 1) * ChunkSize] + OutName = f"{Prefix}{i}.md" + OutPath = os.path.join(Dir, OutName) + try: + with open(OutPath, "w", encoding="utf-8") as Out: + Out.write(Banner(Title, Dir, len(Matched), Total, i, ChunkTotal, OutName)) + Out.write(Chunk) + except OSError as Exc: + print(f"错误: 写入 {OutName} 失败: {Exc}", file=sys.stderr) + return 1 + print(f"{OutName}: {len(Chunk)} 字节") + + print(f"wiki 合并完成: {len(Matched)} 个文件 → {ChunkTotal} 块(前缀 {Prefix},每块 {ChunkKb}KB)") + print("【弱时效性】以上为生成时刻快照,请以 wiki 目录下实时文件为准。") + return 0 + + +def PrintUsage() -> None: + print("用法: python MergeWiki.py [输出前缀] [块大小KB]", file=sys.stderr) + print(f" 默认: 前缀 {DEFAULT_PREFIX},块大小 {DEFAULT_CHUNK_KB}KB", file=sys.stderr) + print(" 合并本目录下所有 *.md/*.MD → <前缀>0.md, <前缀>1.md, ...", file=sys.stderr) + print("【弱时效性】产出为生成时刻快照,分析结论请以实时文件为准。", file=sys.stderr) + + +def main() -> int: + Args = sys.argv[1:] + Prefix = DEFAULT_PREFIX + ChunkKb = DEFAULT_CHUNK_KB + + if len(Args) >= 1 and Args[0] not in ("-h", "--help"): + Prefix = Args[0] + if len(Args) >= 2: + try: + ChunkKb = int(Args[1]) + except ValueError: + print(f"错误: 块大小 '{Args[1]}' 不是整数", file=sys.stderr) + PrintUsage() + return 1 + if len(Args) > 2 or (len(Args) >= 1 and Args[0] in ("-h", "--help")): + PrintUsage() + return 1 + + return MergeWiki(HERE, Prefix, ChunkKb) + + +if __name__ == "__main__": + sys.exit(main())