feat(cms): edit entries in place with textReplacements and pick the response shape - #895
Open
kmonsoe wants to merge 1 commit into
Open
feat(cms): edit entries in place with textReplacements and pick the response shape#895kmonsoe wants to merge 1 commit into
kmonsoe wants to merge 1 commit into
Conversation
…esponse shape cms_update_entry takes textReplacements — ordered, all-or-nothing exact-match edits inside text, markdown, rich_text, array-of-text and blocks fields — so an agent can change a sentence without regenerating the article. Entry-returning write tools take responseFormat (full | summary); publish, unpublish and schedule default to summary since they do not change content. cms_get_entry takes fields to project data. New skill://cms/revise-entry documents the loop. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJjhaB9bMU1agbqVKTwbB1
This was referenced Sep 5, 2026
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.
Why
Revising a blog article today means resending the whole body: a
markdownfield is one string, and ablocksbody is one array, so changing a sentence in one prose block regenerates every block. For an LLM that is the slow and expensive direction, and a regenerated body drifts, drops paragraphs, and manglesasset://tokens.What
cms_update_entrygainstextReplacements— an ordered, all-or-nothing list of{ field, oldText, newText, replaceAll? }edits applied to the stored text of atext,markdown,rich_text, array-of-text orblocksfield.oldTextmust match exactly once, or setreplaceAll. Zero matches fails withcms_replacement_no_match, several withcms_replacement_ambiguous; nothing is written andversiondoes not move.blocksfield the match runs across the prose of every block; block type names, keys and non-text props are never matched.asset://token or as the public URLcms_get_entryshowed. The server maps URLs back to the token before matching, so the image stays tracked.dataortextReplacements, not both./v1/cms/drafts/:idPATCH accepts the same field so both surfaces stay thin wrappers overupdateEntry.responseFormat: "full" | "summary"on every entry-returning write tool.summaryis thecms_list_entriesshape. Create, update and restore default tofull; publish, unpublish and schedule default tosummarybecause they do not change content.cms_get_entrytakesfieldsto projectdata, mirroringcms_list_entries.Design notes
The shape follows what agent-facing content APIs have converged on: Notion's
update_contentand Anthropic's text editor tool both use exact-matchold_str/new_strwith a replace-all switch, and Sanity mixes whole-value sets with in-string patches in one call. It is deliberately two flat optional siblings on the one update tool rather than acommanddiscriminator — theoneOfshape Notion's MCP tool uses is what strict-validation hosts have rejected.Skills
New
skill://cms/revise-entryowns the editing loop.publish-entry,upload-asset-and-embed,migrate-contentandauthor-with-blocksnow show the replacement flow instead of resending bodies. Fixtures regenerated.Tests
common/text-replacements.test.ts: match counting, ordering, atomicity, ambiguity, replaceAll.cms.fields.test.ts: block traversal, type/key immunity, array-of-text, no-text fields.cms.service.test.ts: happy path, coded failures leave the row untouched, unknown/non-text/overlapping fields, block prose + public-URL quoting round-trips to the storedasset://token,fieldsprojection, summary presenter.cms.integration.test.ts: the whole surface through/mcp, including default response shapes on publish/unpublish.A follow-up PR adds the same
textReplacementsandresponseFormatto the KB document tools.🤖 Generated with Claude Code
https://claude.ai/code/session_01VJjhaB9bMU1agbqVKTwbB1