diff --git a/src/langbot/pkg/agent/runner/interaction_manager.py b/src/langbot/pkg/agent/runner/interaction_manager.py index 78d16855a..2fa371770 100644 --- a/src/langbot/pkg/agent/runner/interaction_manager.py +++ b/src/langbot/pkg/agent/runner/interaction_manager.py @@ -186,6 +186,8 @@ class InteractionManager: if not isinstance(capabilities, InteractionDeliveryCapabilities): capabilities = InteractionDeliveryCapabilities.model_validate(capabilities) supported_apis = adapter.get_supported_apis() if callable(getattr(adapter, 'get_supported_apis', None)) else [] + if supported_apis and 'send_interaction' not in supported_apis: + capabilities = InteractionDeliveryCapabilities(text_fallback=capabilities.text_fallback) if supported_apis and 'interaction.acknowledge' not in supported_apis: capabilities.supports_updates = False normalized, degraded, use_text, issues = self._normalize_request(request, capabilities, on_unsupported) @@ -265,7 +267,7 @@ class InteractionManager: except Exception as exc: self._warning(f'Failed to update interaction card: {exc}') if original_deadline is not None: - runtime['deadline_at'] = float(original_deadline) + time.time() - started_at + runtime['deadline_at'] = float(original_deadline) + (time.time() - started_at) return { 'status': 'timeout' if terminal == 'expired' else 'submitted', 'submission': submission, @@ -287,7 +289,7 @@ class InteractionManager: raise finally: if original_deadline is not None: - runtime['deadline_at'] = float(original_deadline) + time.time() - started_at + runtime['deadline_at'] = float(original_deadline) + (time.time() - started_at) self._waiters.pop(key, None) self._responders.pop(key, None) self._callback_contexts.pop(key, None) diff --git a/tests/unit_tests/agent/test_interaction_manager.py b/tests/unit_tests/agent/test_interaction_manager.py index 37aa1345e..a85cf7cf8 100644 --- a/tests/unit_tests/agent/test_interaction_manager.py +++ b/tests/unit_tests/agent/test_interaction_manager.py @@ -1059,3 +1059,29 @@ async def test_unsupported_error_does_not_persist_request(): ) assert result['unsupported'][0]['path'] == 'platform' assert store.record is None + + +@pytest.mark.asyncio +async def test_advertised_card_shape_without_send_api_is_unsupported(): + class UnavailableCardAdapter(BlockingAdapter): + def get_supported_apis(self): + return ['send_message'] + + store = BlockingStore() + manager = InteractionManager(SimpleNamespace(), store=store) + result = await manager.request_interaction( + session=_blocking_session(), + adapter=UnavailableCardAdapter(), + request_payload={ + 'interaction_id': 'unavailable', + 'title': 'Approve?', + 'actions': [ + {'id': 'yes', 'label': 'Yes'}, + ], + }, + timeout=1, + on_unsupported='error', + responders='actor', + ) + assert result['unsupported'][0]['reason'] == 'native_interactions_unavailable' + assert store.record is None