@hanna84/mcp-writing 2.12.3 → 2.12.4
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.
- package/CHANGELOG.md +10 -0
- package/package.json +1 -1
- package/tools/editing.js +42 -7
package/CHANGELOG.md
CHANGED
|
@@ -4,11 +4,21 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [v2.12.4](https://github.com/hannasdev/mcp-writing.git
|
|
8
|
+
/compare/v2.12.3...v2.12.4)
|
|
9
|
+
|
|
10
|
+
- fix: detect no-op commit_edit proposals [`#117`](https://github.com/hannasdev/mcp-writing.git
|
|
11
|
+
/pull/117)
|
|
12
|
+
|
|
7
13
|
#### [v2.12.3](https://github.com/hannasdev/mcp-writing.git
|
|
8
14
|
/compare/v2.12.2...v2.12.3)
|
|
9
15
|
|
|
16
|
+
> 27 April 2026
|
|
17
|
+
|
|
10
18
|
- docs: refine landing page copy and visuals [`#116`](https://github.com/hannasdev/mcp-writing.git
|
|
11
19
|
/pull/116)
|
|
20
|
+
- Release 2.12.3 [`97ed1f6`](https://github.com/hannasdev/mcp-writing.git
|
|
21
|
+
/commit/97ed1f69fa2419dc0875792e048886d96e054cba)
|
|
12
22
|
|
|
13
23
|
#### [v2.12.2](https://github.com/hannasdev/mcp-writing.git
|
|
14
24
|
/compare/v2.12.1...v2.12.2)
|
package/package.json
CHANGED
package/tools/editing.js
CHANGED
|
@@ -5,6 +5,14 @@ import yaml from "js-yaml";
|
|
|
5
5
|
import { createSnapshot, listSnapshots } from "../git.js";
|
|
6
6
|
import { getFileWriteDiagnostics, readMeta, indexSceneFile } from "../sync.js";
|
|
7
7
|
|
|
8
|
+
function renderSceneContent(metadata, revisedProse) {
|
|
9
|
+
const hasFrontmatter = metadata && Object.keys(metadata).length > 0;
|
|
10
|
+
const normalizedProse = revisedProse.replace(/\r?\n$/, "");
|
|
11
|
+
return hasFrontmatter
|
|
12
|
+
? `---\n${yaml.dump(metadata)}---\n\n${normalizedProse}\n`
|
|
13
|
+
: `${normalizedProse}\n`;
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
export function registerEditingTools(s, {
|
|
9
17
|
db,
|
|
10
18
|
SYNC_DIR,
|
|
@@ -36,6 +44,7 @@ export function registerEditingTools(s, {
|
|
|
36
44
|
try {
|
|
37
45
|
const raw = fs.readFileSync(scene.file_path, "utf8");
|
|
38
46
|
const { data: metadata, content: currentProse } = matter(raw);
|
|
47
|
+
const renderedContent = renderSceneContent(metadata, revised_prose);
|
|
39
48
|
|
|
40
49
|
const currentLines = currentProse.trim().split("\n");
|
|
41
50
|
const revisedLines = revised_prose.trim().split("\n");
|
|
@@ -60,17 +69,28 @@ export function registerEditingTools(s, {
|
|
|
60
69
|
scene_file_path: scene.file_path,
|
|
61
70
|
instruction,
|
|
62
71
|
revised_prose,
|
|
72
|
+
rendered_content: renderedContent,
|
|
63
73
|
original_prose: currentProse,
|
|
64
74
|
metadata,
|
|
65
75
|
created_at: new Date().toISOString(),
|
|
66
76
|
});
|
|
67
77
|
|
|
78
|
+
const noop = renderedContent === raw;
|
|
79
|
+
const diffPreview = noop
|
|
80
|
+
? "(no changes)"
|
|
81
|
+
: diffLines.length > 0
|
|
82
|
+
? diffLines.join("\n")
|
|
83
|
+
: "(file changes are not visible in the prose preview; they may be due to frontmatter or whitespace/newline formatting)";
|
|
84
|
+
|
|
68
85
|
return jsonResponse({
|
|
69
86
|
proposal_id: proposalId,
|
|
70
87
|
scene_id,
|
|
71
88
|
instruction,
|
|
72
|
-
diff_preview:
|
|
73
|
-
|
|
89
|
+
diff_preview: diffPreview,
|
|
90
|
+
noop,
|
|
91
|
+
note: noop
|
|
92
|
+
? "This proposal matches the current scene file. Calling commit_edit will be a no-op."
|
|
93
|
+
: "Review the diff above. Call commit_edit with this proposal_id to apply the change.",
|
|
74
94
|
});
|
|
75
95
|
} catch (err) {
|
|
76
96
|
if (err.code === "ENOENT") {
|
|
@@ -152,10 +172,24 @@ export function registerEditingTools(s, {
|
|
|
152
172
|
);
|
|
153
173
|
}
|
|
154
174
|
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
175
|
+
const content = proposal.rendered_content ?? renderSceneContent(proposal.metadata, proposal.revised_prose);
|
|
176
|
+
const currentRaw = fs.readFileSync(proposal.scene_file_path, "utf8");
|
|
177
|
+
|
|
178
|
+
if (currentRaw === content) {
|
|
179
|
+
const { meta: canonicalMeta } = readMeta(proposal.scene_file_path, SYNC_DIR, { writable: false });
|
|
180
|
+
const { content: currentProse } = matter(currentRaw);
|
|
181
|
+
indexSceneFile(db, SYNC_DIR, proposal.scene_file_path, canonicalMeta, currentProse);
|
|
182
|
+
pendingProposals.delete(proposal_id);
|
|
183
|
+
|
|
184
|
+
return jsonResponse({
|
|
185
|
+
ok: true,
|
|
186
|
+
scene_id,
|
|
187
|
+
proposal_id,
|
|
188
|
+
snapshot_commit: null,
|
|
189
|
+
noop: true,
|
|
190
|
+
message: `Proposal for scene '${scene_id}' matches the current file. Nothing was written.`,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
159
193
|
|
|
160
194
|
const snapshot = createSnapshot(SYNC_DIR, proposal.scene_file_path, scene_id, proposal.instruction);
|
|
161
195
|
|
|
@@ -172,7 +206,8 @@ export function registerEditingTools(s, {
|
|
|
172
206
|
scene_id,
|
|
173
207
|
proposal_id,
|
|
174
208
|
snapshot_commit: snapshot.commit_hash,
|
|
175
|
-
|
|
209
|
+
noop: false,
|
|
210
|
+
message: `Applied edit to scene '${scene_id}'${snapshot.commit_hash ? ` (snapshot: ${snapshot.commit_hash.substring(0, 7)})` : " (no pre-edit snapshot needed)"}`,
|
|
176
211
|
});
|
|
177
212
|
} catch (err) {
|
|
178
213
|
if (err.code === "ENOENT") {
|