fix(telegram): advance markdown split on long single-line fences
When a fenced code body has no interior newlines, the splitter cut at the opening fence line and re-emitted the same content forever. Prefer breaks inside the body after the fence so long JSON/minified blocks still split.
This commit is contained in:
@@ -90,18 +90,27 @@ def _split_telegram_markdown(content: str, max_len: int) -> list[str]:
|
|||||||
min_code_pos = len(fence)
|
min_code_pos = len(fence)
|
||||||
if content.startswith(fence + "\n"):
|
if content.startswith(fence + "\n"):
|
||||||
min_code_pos += 1
|
min_code_pos += 1
|
||||||
if pos < min_code_pos and min_code_pos + len(closing) > max_len:
|
# When the only break in range is the opening fence newline,
|
||||||
chunks.append(content[:max_len])
|
# cutting there re-emits the same fence and never advances.
|
||||||
content = content[max_len:].lstrip()
|
if pos < min_code_pos:
|
||||||
continue
|
if min_code_pos + len(closing) > max_len:
|
||||||
if pos + len(closing) > max_len:
|
chunks.append(content[:max_len])
|
||||||
|
content = content[max_len:].lstrip()
|
||||||
|
continue
|
||||||
|
budget = max_len - len(closing)
|
||||||
|
recut = content[:budget]
|
||||||
|
adjusted = recut.rfind("\n", min_code_pos)
|
||||||
|
if adjusted < min_code_pos:
|
||||||
|
adjusted = recut.rfind(" ", min_code_pos)
|
||||||
|
pos = adjusted if adjusted >= min_code_pos else budget
|
||||||
|
elif pos + len(closing) > max_len:
|
||||||
budget = max_len - len(closing)
|
budget = max_len - len(closing)
|
||||||
if budget > 0:
|
if budget > 0:
|
||||||
recut = content[:budget]
|
recut = content[:budget]
|
||||||
adjusted = recut.rfind("\n")
|
adjusted = recut.rfind("\n", min_code_pos)
|
||||||
if adjusted <= 0:
|
if adjusted < min_code_pos:
|
||||||
adjusted = recut.rfind(" ")
|
adjusted = recut.rfind(" ", min_code_pos)
|
||||||
pos = adjusted if adjusted > 0 else budget
|
pos = adjusted if adjusted >= min_code_pos else budget
|
||||||
else:
|
else:
|
||||||
closing = "```"
|
closing = "```"
|
||||||
pos = max_len - len(closing)
|
pos = max_len - len(closing)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from nanobot.bus.events import OutboundMessage
|
|||||||
from nanobot.bus.outbound_events import ProgressEvent
|
from nanobot.bus.outbound_events import ProgressEvent
|
||||||
from nanobot.bus.queue import MessageBus
|
from nanobot.bus.queue import MessageBus
|
||||||
from nanobot.channels.telegram.runtime import (
|
from nanobot.channels.telegram.runtime import (
|
||||||
|
TELEGRAM_MAX_MESSAGE_LEN,
|
||||||
TELEGRAM_REPLY_CONTEXT_MAX_LEN,
|
TELEGRAM_REPLY_CONTEXT_MAX_LEN,
|
||||||
TelegramChannel,
|
TelegramChannel,
|
||||||
TelegramConfig,
|
TelegramConfig,
|
||||||
@@ -243,6 +244,30 @@ def test_split_telegram_markdown_leading_whitespace_before_fence() -> None:
|
|||||||
_assert_code_blocks_render_balanced(chunks)
|
_assert_code_blocks_render_balanced(chunks)
|
||||||
|
|
||||||
|
|
||||||
|
def test_split_telegram_markdown_long_single_line_code_body() -> None:
|
||||||
|
"""Long fence bodies with no interior newlines must still advance."""
|
||||||
|
body = "a" * 4500
|
||||||
|
content = f"```\n{body}\n```"
|
||||||
|
|
||||||
|
chunks = _split_telegram_markdown(content, TELEGRAM_MAX_MESSAGE_LEN)
|
||||||
|
|
||||||
|
assert len(chunks) > 1
|
||||||
|
assert all(len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN for chunk in chunks)
|
||||||
|
assert chunks[0].startswith("```\n")
|
||||||
|
assert chunks[0].endswith("\n```")
|
||||||
|
assert chunks[1].startswith("```\n")
|
||||||
|
reassembled = []
|
||||||
|
for chunk in chunks:
|
||||||
|
part = chunk.split("\n", 1)[1]
|
||||||
|
if part.endswith("\n```"):
|
||||||
|
part = part[:-4]
|
||||||
|
elif part.endswith("```"):
|
||||||
|
part = part[:-3]
|
||||||
|
reassembled.append(part)
|
||||||
|
assert "".join(reassembled) == body
|
||||||
|
_assert_code_blocks_render_balanced(chunks)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_start_creates_separate_pools_with_proxy(monkeypatch) -> None:
|
async def test_start_creates_separate_pools_with_proxy(monkeypatch) -> None:
|
||||||
_FakeHTTPXRequest.clear()
|
_FakeHTTPXRequest.clear()
|
||||||
|
|||||||
Reference in New Issue
Block a user