uni-diff-patch 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,194 @@
1
+ Metadata-Version: 2.3
2
+ Name: uni-diff-patch
3
+ Version: 0.0.1
4
+ Summary: MCP server and CLI tool for generating valid unified diff patches deterministically
5
+ Author: LimLLL
6
+ Author-email: LimLLL <github@awebapp.useforall.com>
7
+ Requires-Dist: mpatch
8
+ Requires-Dist: mcp[cli]
9
+ Requires-Dist: click
10
+ Requires-Dist: pydantic>=2.13.4
11
+ Requires-Python: >=3.12
12
+ Description-Content-Type: text/markdown
13
+
14
+ # uni-diff-patch
15
+
16
+ MCP server + CLI tool for generating valid unified diff patches deterministically.
17
+
18
+ LLM provides content or search/replace pairs, the tool computes correct diffs via [mpatch](https://github.com/Romelium/mpatch) (Rust) — no more broken hunks, no more `git apply` failures.
19
+
20
+ ---
21
+
22
+ MCP 服务器 + CLI 工具,确定性生成合法的 unified diff patch。
23
+
24
+ LLM 只需提供文件内容或搜索替换对,工具通过 [mpatch](https://github.com/Romelium/mpatch) (Rust) 计算正确的 diff — 不再有坏掉的 hunk,`git apply` 不再失败。
25
+
26
+ ## Install / 安装
27
+
28
+ ```bash
29
+ uv add uni-diff-patch # as dependency / 作为依赖
30
+ uvx uni-diff-patch --help # run directly / 直接运行
31
+ ```
32
+
33
+ ## CLI / 命令行
34
+
35
+ ```bash
36
+ # Generate patch from JSON spec / 从 JSON spec 生成 patch
37
+ uni-diff-patch generate --spec changes.json -o output.diff
38
+
39
+ # Generate with work_dir (for absolute paths) / 指定工作目录(用于绝对路径)
40
+ uni-diff-patch generate --spec changes.json --work-dir /path/to/project
41
+
42
+ # Validate a patch / 验证 patch
43
+ uni-diff-patch validate output.diff
44
+ uni-diff-patch validate output.diff --git-check --work-dir /path/to/repo
45
+
46
+ # Start MCP server / 启动 MCP 服务器
47
+ uni-diff-patch serve
48
+ ```
49
+
50
+ ## MCP Configuration / MCP 配置
51
+
52
+ ```json
53
+ {
54
+ "mcpServers": {
55
+ "uni-diff-patch": {
56
+ "command": "uvx",
57
+ "args": ["uni-diff-patch", "serve"]
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ ## JSON Spec Format / JSON Spec 格式
64
+
65
+ All modes are specified in a `changes` array. Each change requires `file_path` and `mode`.
66
+
67
+ 所有模式通过 `changes` 数组指定,每个变更需要 `file_path` 和 `mode`。
68
+
69
+ ### file_content — Full new content / 完整新内容
70
+
71
+ Tool reads original from disk and diffs. / 工具从磁盘读取原文件并生成 diff。
72
+
73
+ ```json
74
+ {
75
+ "changes": [{
76
+ "file_path": "src/main.py",
77
+ "mode": "file_content",
78
+ "new_content": "def main():\n print('hello')\n"
79
+ }]
80
+ }
81
+ ```
82
+
83
+ ### search_replace — Targeted replacements / 精准替换(最省 token)
84
+
85
+ ```json
86
+ {
87
+ "changes": [{
88
+ "file_path": "src/main.py",
89
+ "mode": "search_replace",
90
+ "replacements": [
91
+ {"search": "print('hello')", "replace": "print('world')"},
92
+ {"search": "old_func()", "replace": "new_func()", "line_hint": 42}
93
+ ]
94
+ }]
95
+ }
96
+ ```
97
+
98
+ `line_hint`: approximate line number for disambiguation when `search` matches multiple locations.
99
+
100
+ `line_hint`:当 `search` 匹配多处时,用大致行号消歧(选最近的匹配)。
101
+
102
+ ### create_file — New file / 新建文件
103
+
104
+ ```json
105
+ {
106
+ "changes": [{
107
+ "file_path": "src/new_module.py",
108
+ "mode": "create_file",
109
+ "new_content": "# New module\ndef init():\n pass\n"
110
+ }]
111
+ }
112
+ ```
113
+
114
+ ### delete_file — Remove file / 删除文件
115
+
116
+ ```json
117
+ {
118
+ "changes": [{
119
+ "file_path": "src/deprecated.py",
120
+ "mode": "delete_file"
121
+ }]
122
+ }
123
+ ```
124
+
125
+ ### text_pair — Both old and new text / 直接传入新旧文本(不读磁盘)
126
+
127
+ ```json
128
+ {
129
+ "changes": [{
130
+ "file_path": "virtual/path.py",
131
+ "mode": "text_pair",
132
+ "old_text": "x = 1\n",
133
+ "new_text": "x = 2\n"
134
+ }]
135
+ }
136
+ ```
137
+
138
+ ### rename_file — Rename/move / 重命名/移动文件
139
+
140
+ Optionally with content change. / 可同时修改内容。
141
+
142
+ ```json
143
+ {
144
+ "changes": [{
145
+ "file_path": "src/old_name.py",
146
+ "mode": "rename_file",
147
+ "new_path": "src/new_name.py",
148
+ "new_content": "# Optional modified content\n"
149
+ }]
150
+ }
151
+ ```
152
+
153
+ ### chmod — Permission change / 权限变更
154
+
155
+ Optionally with content change. / 可同时修改内容。
156
+
157
+ ```json
158
+ {
159
+ "changes": [{
160
+ "file_path": "scripts/deploy.sh",
161
+ "mode": "chmod",
162
+ "old_mode": "100644",
163
+ "new_mode": "100755"
164
+ }]
165
+ }
166
+ ```
167
+
168
+ ### Multi-file patch / 多文件合并 patch
169
+
170
+ ```json
171
+ {
172
+ "changes": [
173
+ {"file_path": "src/a.py", "mode": "file_content", "new_content": "..."},
174
+ {"file_path": "src/b.py", "mode": "search_replace", "replacements": [{"search": "old", "replace": "new"}]},
175
+ {"file_path": "src/c.py", "mode": "create_file", "new_content": "..."}
176
+ ],
177
+ "output_path": "changes.diff"
178
+ }
179
+ ```
180
+
181
+ ## Optional Fields / 可选字段
182
+
183
+ | Field / 字段 | Default / 默认值 | Description / 说明 |
184
+ |-------|---------|------------|
185
+ | `encoding` | `"utf-8"` | File encoding for disk-read modes / 磁盘读取模式的文件编码 |
186
+ | `context_lines` | `3` | Context lines in diff / diff 中的上下文行数 |
187
+ | `output_path` | — | Top-level, writes patch to file / 顶层字段,将 patch 写入文件 |
188
+
189
+ ## Development / 开发
190
+
191
+ ```bash
192
+ uv sync
193
+ uv run pytest tests/ -v
194
+ ```
@@ -0,0 +1,13 @@
1
+ uni_diff_patch/__init__.py,sha256=QZHH9fShZy0Uae-0TF-6HN35C_3nCbGHcYE56eNy83E,1066
2
+ uni_diff_patch/cli.py,sha256=XyqjzIUHsli_SGBkbFxxOL7Y02NY_Wz7x54fGgZDE9I,5109
3
+ uni_diff_patch/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ uni_diff_patch/core/diff_engine.py,sha256=lARXSa8iacdLRRZlxI_H21hgwf2q9HC1PR1Ob0oddjI,13358
5
+ uni_diff_patch/core/search_replace.py,sha256=kwUfr-SqB9oZJwXK0A3LOEmccXi_fx5SGQD_MPN83Rk,4592
6
+ uni_diff_patch/core/validator.py,sha256=qf66MXYT3zvHsqQ3l6PlvyK5Go6_DXu89QcIIxlE5cg,6639
7
+ uni_diff_patch/models.py,sha256=M7PcWRcUWUz0CO8MK7z5CDwYxpoN-MCmihvAq7zH9x0,6154
8
+ uni_diff_patch/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ uni_diff_patch/server.py,sha256=NAjVofdUUqL3VI3AgtCT7ky7Csf9atSenF6d3-734cM,4845
10
+ uni_diff_patch-0.0.1.dist-info/WHEEL,sha256=YR4QUxGCbsyoOnWBVTv-p1I4yc3seKGPev46mvmc8Cg,81
11
+ uni_diff_patch-0.0.1.dist-info/entry_points.txt,sha256=SMaBpCbADshKmWiXYPpy_PSVvKWf0KQcwNJXi_FIsoM,60
12
+ uni_diff_patch-0.0.1.dist-info/METADATA,sha256=mK4hc0wOlTpdUdyfNvtxTvZJf4cRY3uQ73_7vYX-sM4,4870
13
+ uni_diff_patch-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.11.29
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ uni-diff-patch = uni_diff_patch.cli:main
3
+