diff --git a/plugins/platforms/photon/adapter.py b/plugins/platforms/photon/adapter.py index 60d74de41e2ad..731783567dc72 100644 --- a/plugins/platforms/photon/adapter.py +++ b/plugins/platforms/photon/adapter.py @@ -875,19 +875,12 @@ def _normalize_binary_payload( ) ctype = content.get("type") - if ctype == "text": - raw_text = content.get("text") or "" - # iMessage emits U+FFFC OBJECT REPLACEMENT CHARACTER as a transient - # placeholder for some media bubbles (notably voice notes). Photon - # can then deliver the real attachment/voice event immediately - # afterwards with a different message id. If we dispatch the - # placeholder as a standalone text turn, the subsequent media event - # arrives while that turn is active and the gateway sends a bogus - # "Interrupting current task" busy ack. Drop placeholder-only text - # at the platform boundary; the real media event carries the bytes. - if raw_text.strip() == "\ufffc": - logger.debug("[photon] ignoring iMessage object-placeholder text event") - return + # NOTE: U+FFFC OBJECT REPLACEMENT CHARACTER placeholders (transient + # stand-ins for media bubbles) are handled below by the pending-FFFC + # machinery, which both suppresses the bogus text turn AND waits for + # the real attachment with a timeout. Do not early-drop them here — + # that would make the wait/timeout path unreachable (#54514 originally + # dropped them at this boundary; superseded by the FFFC wait). if ctype == "reaction": # Route only tapbacks on messages WE sent — those are implicitly # addressed to the bot (feishu precedent: synthetic text event). diff --git a/tests/plugins/platforms/photon/test_runtime_record.py b/tests/plugins/platforms/photon/test_runtime_record.py index 1b1e650cfc5e8..8090c1a7f03de 100644 --- a/tests/plugins/platforms/photon/test_runtime_record.py +++ b/tests/plugins/platforms/photon/test_runtime_record.py @@ -120,7 +120,8 @@ def _patch_spawn( ) -> None: """Stub everything _start_sidecar touches before the healthz loop.""" sidecar_dir = tmp_path / "sidecar" - (sidecar_dir / "node_modules").mkdir(parents=True) + # sidecar_deps_installed() requires node_modules/spectrum-ts (partial-install guard) + (sidecar_dir / "node_modules" / "spectrum-ts").mkdir(parents=True) monkeypatch.setattr(photon_adapter, "_SIDECAR_DIR", sidecar_dir) monkeypatch.setattr(photon_adapter, "_sidecar_deps_stale", lambda: False)