docs +update --command str_replace parses Markdown inline syntax under --doc-format xml, unlike every other write path
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 17.3k
- Forks
- 1.4k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 105
Description
Bug Description
Under --doc-format xml (the default), docs +update --command str_replace interprets its --content as Lark-flavored Markdown: **text** is stored as a <b> node and `text` as a <code> node.
Every other write path using the very same --doc-format xml — docs +create, and docs +update with append, block_insert_after, block_replace — keeps those exact characters as literal text.
So the same flag value produces two opposite contracts depending on --command, and nothing in the CLI surface says so. --dry-run shows the CLI forwards --content verbatim with "format": "xml", so the divergence lives in how the str_replace command path processes the payload.
Environment
lark-cliversion:1.0.87- Installation method:
npm i -g @larksuite/cli - OS: macOS
- Identity:
--as user
Reproduction
Placeholders below: <doc_token> is the created document token, <block_id> the id returned by docs +fetch --detail with-ids.
# 1. Create a document with the same inline markers in four containers
cat > repro.xml <<'EOF'
<title>xml inline markup repro</title>
<p>A1 **bold** and `code` here</p>
<table><tbody><tr><td><p>B1 **bold** and `code` here</p></td></tr></tbody></table>
<ol><li>C1 **bold** and `code` here</li></ol>
<p>E1 marker here</p>
EOF
lark-cli docs +create --as user --doc-format xml --content "@./repro.xml"
# 2. Append more of the same through the block paths
lark-cli docs +update --as user --doc "<doc_token>" --command append \
--content '<p>F1 **bold** and `code` here</p>'
lark-cli docs +update --as user --doc "<doc_token>" --command block_insert_after \
--block-id "<block_id>" --content '<p>H1 **bold** and `code` here</p>'
# 3. Write the identical characters through str_replace
lark-cli docs +update --as user --doc "<doc_token>" --command str_replace \
--pattern 'E1 marker here' --content 'E1 **bold** and `code` here'
# 4. Read everything back in one call
lark-cli docs +fetch --as user --doc "<doc_token>" --doc-format xml --detail with-ids
Dry-run request for step 3
{
"command": "str_replace",
"content": "E1 **bold** and `code` here",
"format": "xml",
"pattern": "E1 marker here",
"revision_id": -1
}
Actual result
docs +fetch --doc-format xml returns:
<p>A1 **bold** and `code` here</p>
<table>...<td><p>B1 **bold** and `code` here</p></td>...</table>
<ol><li>C1 **bold** and `code` here</li></ol>
<p>F1 **bold** and `code` here</p>
<p>H1 **bold** and `code` here</p>
<p>E1 <b>bold</b> and <code>code</code> here</p> <!-- str_replace only -->
Write path (--doc-format xml) |
**bold** / `code` |
|---|---|
docs +create |
literal text |
docs +update --command append |
literal text |
docs +update --command block_insert_after |
literal text |
docs +update --command block_replace |
literal text |
docs +update --command str_replace |
parsed into <b> / <code> nodes |
The container does not matter: running str_replace over text that lives inside <li> or inside <td><p> converts the markers there too, so the split is purely per-command.
Backslash escaping confirms a Markdown inline parser is active on that path only:
lark-cli docs +update --as user --doc "<doc_token>" --command str_replace \
--pattern 'G1 marker' --content 'G1 literal \*\*stars\*\* and \`ticks\`'
# fetch -> <p>G1 literal **stars** and `ticks`</p> (backslashes consumed, no <b>)
Expected result
With --doc-format xml, all write commands treat --content as XML and store Markdown punctuation as literal text; inline styling comes from <b> / <code>. If str_replace must keep Markdown-style inline parsing, the CLI surface should say so and name the escape form.
Impact on agents
- Silent, undetectable corruption. An agent editing technical prose through
str_replace— regex snippets,**kwargs, glob patterns, shell backticks, Python__init__— gets bold/code nodes it never asked for.resultissuccessandwarningsis[], so nothing in the response reveals it. - Content does not round-trip.
docs +fetch --doc-format xmlreturns**bold**as literal text; feeding that same text back throughstr_replaceturns it into<b>bold</b>. Fetch → edit → write is not idempotent. - The documented contract points the other way.
skills/lark-doc/references/lark-doc-md.mdwarns about the mirror case ("XML 标签会被解析并生效" under--doc-format markdown), butlark-doc-xml.mdandlark-doc-update.mdnever mention Markdown, so an agent reasonably assumes XML mode is XML-only.
Suggestion
Preferred: make format: "xml" mean XML on the str_replace path too, so one flag has one contract.
If that is a deliberate server-side behavior, then document it where agents read: the str_replace row in skills/lark-doc/references/lark-doc-update.md, including the \* escape form. I am happy to send that documentation PR.
Related
- #155 and #941 — over-escaping caused by escape rules lacking trigger context (Markdown path).
- #1680 —
str_replaceandblock_replacedisagreeing about inline<code>nodes; same "two write paths, two contracts" family.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the documented references in skills/lark-doc/references/lark-doc-xml.md and lark-doc-update.md, then compare the str_replace command path with the other XML write paths using the supplied reproduction and dry-run request. Done means XML-mode str_replace has the same literal-text contract as the other write commands, or its Markdown parsing and escape form are explicitly documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- cli, documentation
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100