Skip to content

Commit b8edb60

Browse files
committed
fix: preserve multiline descriptions in legacy toml renderer
1 parent 94ba857 commit b8edb60

2 files changed

Lines changed: 31 additions & 2 deletions

File tree

src/specify_cli/agents.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,9 @@ def render_toml_command(
191191
toml_lines = []
192192

193193
if "description" in frontmatter:
194-
desc = frontmatter["description"].replace('"', '\\"')
195-
toml_lines.append(f'description = "{desc}"')
194+
toml_lines.append(
195+
f'description = {self._render_basic_toml_string(frontmatter["description"])}'
196+
)
196197
toml_lines.append("")
197198

198199
toml_lines.append(f"# Source: {source_id}")
@@ -220,6 +221,18 @@ def render_toml_command(
220221

221222
return "\n".join(toml_lines)
222223

224+
@staticmethod
225+
def _render_basic_toml_string(value: str) -> str:
226+
"""Render *value* as a TOML basic string literal."""
227+
escaped = (
228+
value.replace("\\", "\\\\")
229+
.replace('"', '\\"')
230+
.replace("\n", "\\n")
231+
.replace("\r", "\\r")
232+
.replace("\t", "\\t")
233+
)
234+
return f'"{escaped}"'
235+
223236
def render_skill_command(
224237
self,
225238
agent_name: str,

tests/test_extensions.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import json
1414
import tempfile
1515
import shutil
16+
import tomllib
1617
from pathlib import Path
1718
from datetime import datetime, timezone
1819

@@ -1014,6 +1015,21 @@ def test_render_toml_command_escapes_when_both_triple_quote_styles_exist(self):
10141015
assert "\\n" in output
10151016
assert "\\\"\\\"\\\"" in output
10161017

1018+
def test_render_toml_command_preserves_multiline_description(self):
1019+
"""Multiline descriptions should render as parseable TOML with preserved semantics."""
1020+
from specify_cli.agents import CommandRegistrar as AgentCommandRegistrar
1021+
1022+
registrar = AgentCommandRegistrar()
1023+
output = registrar.render_toml_command(
1024+
{"description": "first line\nsecond line\n"},
1025+
"body",
1026+
"extension:test-ext",
1027+
)
1028+
1029+
parsed = tomllib.loads(output)
1030+
1031+
assert parsed["description"] == "first line\nsecond line\n"
1032+
10171033
def test_register_commands_for_claude(self, extension_dir, project_dir):
10181034
"""Test registering commands for Claude agent."""
10191035
# Create .claude directory

0 commit comments

Comments
 (0)