Add targeted partial content edits#2
Open
jack-arturo wants to merge 2 commits intofeature/media-tool-cleanup-file-uploadfrom
Open
Add targeted partial content edits#2jack-arturo wants to merge 2 commits intofeature/media-tool-cleanup-file-uploadfrom
jack-arturo wants to merge 2 commits intofeature/media-tool-cleanup-file-uploadfrom
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
update_contentcurrently treats the post body as an all-or-nothing string. That works for small edits, but it is expensive for MCP/LLM workflows because even a one-line change requires resending the full document. WordPress itself supports partial field updates at the post level, but it does not offer substring-level edits insidecontent, so the server needs to provide that behavior if we want to reduce token usage.A related problem showed up immediately in review: even when targeted edits work, callers often copy
target_textfrom rendered HTML. That is unreliable because rendered WordPress output can differ from the stored raw document. Entities may be escaped, marker comments may be wrapped, and image markup can diverge from what was originally saved.Approach
This PR adds a new
content_editcontract toupdate_contentand mirrors the same contract infind_content_by_url.update_fields.Supported operations:
appendprependinsert_beforeinsert_afterreplaceThe existing
contentfield remains the full-replacement path.contentandcontent_editare mutually exclusive so the tool contract stays explicit.Follow-up from review:
include_raw_contenttoget_contentinclude_raw_contenttofind_content_by_urlcontent_rawfield in those responses so callers can copy the exact raw fragment needed forcontent_edit.target_textWhy This Design
The goal here is to reduce token cost without introducing a fragile document-editing system.
I intentionally kept the edit path deterministic:
target_textforinsert_before,insert_after, andreplaceoccurrenceis providedThat keeps the feature useful for practical marker-based and fragment-based edits while avoiding a much larger HTML or Gutenberg AST editing project.
The read-path follow-up is meant to remove the biggest usability pain in that design. Instead of making the matcher heuristic, the server now exposes the exact stored raw content when requested.
How It Works
When a partial edit is requested, the server:
context=editcontent.rawprocessContentflowcontentback through the normal WordPress update endpointFor exact-match discovery,
get_content(include_raw_content=true)andfind_content_by_url(include_raw_content=true)also fetch withcontext=editand includecontent_rawin the returned payload.This means callers can now:
content_rawor a fragment from itcontent_edit.target_textAPI Surface
New edit object on
update_content:content_edit.operationcontent_edit.valuecontent_edit.target_textcontent_edit.occurrencecontent_edit.content_formatcontent_edit.convert_to_blocksThe same object is supported under
find_content_by_url.update_fields.content_edit.New read flags:
get_content.include_raw_contentfind_content_by_url.include_raw_contentNew convenience field in raw-read responses:
content_rawValidation added:
content+content_edittogethertarget_textoccurrencedisambiguatescontent.rawImplementation Notes
src/tools/unified-content.tsupdate_contentandfind_content_by_urlreuse the same content-update builder so the behavior stays alignedcontext=editwhen explicitly requestedcontent.rawVerification
npm run buildhttps://drunk.supportcurl .../wp-json/wp/v2/posts/<id>?context=editupdate_contentwithcontent_edit.replacefind_content_by_urlwithcontent_edit.appendget_content(include_raw_content=true)returnscontent_rawfind_content_by_url(include_raw_content=true)returnscontent_rawcurlcurlchecksRepresentative
curlcheck showing why raw content matters:{ "id": 576, "raw": "<p>Smoke & verify 20260325022944</p>\n<!-- raw-marker -->\n<p>Target & replace 20260325022944</p>\n<!-- /raw-marker -->", "rendered": "<p>Smoke & verify 20260325022944</p>\n<p><!-- raw-marker --></p>\n<p>Target & replace 20260325022944</p>\n<p><!-- /raw-marker --></p>\n" }Representative cleanup check:
{ "code": "rest_post_invalid_id", "message": "Invalid post ID.", "data": { "status": 404 } }Stack Note
This PR is intentionally stacked on top of
feature/media-tool-cleanup-file-upload, which is upstream PRInstaWP/mcp-wp#13. Once#13merges, this branch can be rebased ontomainand opened upstream as a normal standalone PR.