fix(slack): drop markdown_text from native task-card appendStream payload

chat.appendStream rejects a request carrying both markdown_text and
chunks with `cannot_provide_both_markdown_text_and_chunks`, so every
native task-card update failed and each turn silently downgraded to the
plain-text fallback message (#87743). The chunks are the native
rendering; the gateway caller keeps its own editable-text fallback rail
for when the native call itself fails, so the markdown_text field was
both rejected and redundant.
Fixes #87743
This commit is contained in:
liuhao1024
2026-08-16 22:24:15 +08:00
committed by Teknium
parent 0edab1ac4d
commit 7fc0c649ff
2 changed files with 42 additions and 2 deletions

View File

@@ -1934,8 +1934,9 @@ class SlackAdapter(BasePlatformAdapter):
chunks.extend(self._task_update_chunk(task) for task in tasks)
append_payload: Dict[str, Any] = {
"channel": chat_id, "ts": stream.stream_ts, "chunks": chunks}
if fallback_text:
append_payload["markdown_text"] = fallback_text
# chunks-only: Slack rejects markdown_text alongside chunks
# (cannot_provide_both_markdown_text_and_chunks, #87743); the gateway owns
# the editable-text fallback rail that fallback_text feeds when this call fails.
await client.api_call("chat.appendStream", json=append_payload)
return SendResult(success=True, message_id=stream.stream_ts)
except Exception as exc: # pragma: no cover - defensive logging

View File

@@ -5143,6 +5143,45 @@ class TestNativeTaskCardProgress:
]
assert adapter._native_task_card_streams == {}
@pytest.mark.asyncio
async def test_append_payload_never_mixes_markdown_text_with_chunks(
self, adapter
):
"""#87743: chat.appendStream rejects a request carrying both
markdown_text and chunks (`cannot_provide_both_markdown_text_and_chunks`),
which made every native task-card update fail and silently downgraded
each turn to the plain-text fallback. The fallback_text must never be
attached to the chunks payload."""
client = adapter._app.client
async def api_call(method, *, json):
if method == "chat.startStream":
return {"ts": "stream-1"}
return {"ok": True}
client.api_call.side_effect = api_call
result = await adapter.send_native_task_card_progress(
"C1",
[{"id": "call-1", "title": "terminal", "status": "in_progress"}],
metadata={"thread_id": "thread-1"},
fallback_text="fallback progress text",
)
assert result.success is True
append_calls = [
call
for call in client.api_call.await_args_list
if call.args[0] == "chat.appendStream"
]
assert append_calls, "expected an appendStream call"
payload = append_calls[0].kwargs["json"]
assert "chunks" in payload
assert "markdown_text" not in payload, (
"appendStream must not mix markdown_text with chunks — Slack "
"rejects the pair and the whole native card fails (#87743)"
)
# ---------------------------------------------------------------------------
# TestSlackAuthoredTextDeduplication