diff --git a/src/langbot/libs/dingtalk_api/a2ui.py b/src/langbot/libs/dingtalk_api/a2ui.py index b5c939a1f..2b28882ef 100644 --- a/src/langbot/libs/dingtalk_api/a2ui.py +++ b/src/langbot/libs/dingtalk_api/a2ui.py @@ -22,22 +22,24 @@ def brand_components() -> list[dict[str, typing.Any]]: { 'id': 'langbot-brand', 'component': 'Row', - 'children': ['langbot-brand-icon', 'langbot-brand-link'], + 'children': ['langbot-generated', 'langbot-brand-link'], 'align': 'center', - 'gap': 4, + 'justify': 'spaceBetween', + 'gap': 8, }, { - 'id': 'langbot-brand-icon', - 'component': 'Image', - 'url': LANGBOT_LOGO_URL, - 'variant': 'icon', - 'fit': 'contain', - 'previewEnabled': False, + 'id': 'langbot-generated', + 'component': 'Text', + 'text': 'AI-generated', + 'variant': 'caption', }, { 'id': 'langbot-brand-link', - 'component': 'Markdown', - 'content': f'[LangBot]({LANGBOT_CARD_URL})', + 'component': 'Text', + 'text': 'LangBot', + 'variant': 'caption', + 'icon': {'url': LANGBOT_LOGO_URL}, + 'onLinkClick': {'functionCall': {'call': 'openUrl', 'args': {'url': LANGBOT_CARD_URL}}}, }, ] @@ -122,7 +124,7 @@ def text_card_components() -> list[dict[str, typing.Any]]: { 'id': 'root', 'component': 'Column', - 'children': ['langbot-brand', 'content'], + 'children': ['content', 'langbot-brand'], 'gap': 8, }, { diff --git a/src/langbot/pkg/platform/adapters/dingtalk/interaction.py b/src/langbot/pkg/platform/adapters/dingtalk/interaction.py index f97cc955c..a36e89375 100644 --- a/src/langbot/pkg/platform/adapters/dingtalk/interaction.py +++ b/src/langbot/pkg/platform/adapters/dingtalk/interaction.py @@ -150,7 +150,7 @@ def _build_interaction_messages( ) children.append(button_id) - children.insert(0, 'langbot-brand') + children.append('langbot-brand') components.extend(brand_components()) components.insert(0, {'id': 'root', 'component': 'Column', 'children': children, 'gap': 12}) return {'form': form}, components, field_types diff --git a/src/langbot/pkg/platform/sources/dingtalk.py b/src/langbot/pkg/platform/sources/dingtalk.py index d984af805..e1ca4f7f8 100644 --- a/src/langbot/pkg/platform/sources/dingtalk.py +++ b/src/langbot/pkg/platform/sources/dingtalk.py @@ -520,7 +520,7 @@ def _dingtalk_a2ui_form( ] ) children.append(button_id) - children.insert(0, 'langbot-brand') + children.append('langbot-brand') components.extend(brand_components()) return data, components diff --git a/tests/unit_tests/platform/test_dingtalk_adapter.py b/tests/unit_tests/platform/test_dingtalk_adapter.py index 02eba76d1..a5fb28382 100644 --- a/tests/unit_tests/platform/test_dingtalk_adapter.py +++ b/tests/unit_tests/platform/test_dingtalk_adapter.py @@ -53,7 +53,7 @@ def test_dingtalk_dify_input_card_uses_a2ui_binding_and_required_check(): assert field['value'] == {'path': '/form/value'} assert button['action']['event']['context']['input'] == {'path': '/form/value'} assert button['checks'][0]['condition']['call'] == 'required' - assert components[0]['children'][0] == 'langbot-brand' + assert components[0]['children'][-1] == 'langbot-brand' assert any(component['id'] == 'langbot-brand-link' for component in components) diff --git a/tests/unit_tests/platform/test_dingtalk_api.py b/tests/unit_tests/platform/test_dingtalk_api.py index 0ab1ad764..f51c6f4e9 100644 --- a/tests/unit_tests/platform/test_dingtalk_api.py +++ b/tests/unit_tests/platform/test_dingtalk_api.py @@ -35,14 +35,18 @@ def test_text_card_keeps_brand_when_content_updates(): components = create_text_card_messages('surface-id', 'hello')[2]['updateComponents']['components'] by_id = {component['id']: component for component in components} - assert by_id['root']['children'] == ['langbot-brand', 'content'] - assert by_id['langbot-brand']['children'] == ['langbot-brand-icon', 'langbot-brand-link'] - assert by_id['langbot-brand-icon']['url'] == 'https://langbot.app/logo-blue.png' - assert by_id['langbot-brand-icon']['previewEnabled'] is False - assert by_id['langbot-brand-link']['component'] == 'Markdown' - assert by_id['langbot-brand-link']['content'] == ( - '[LangBot](https://langbot.app?utm_source=dingtalk&utm_medium=bot_card&utm_campaign=langbot)' - ) + assert by_id['root']['children'] == ['content', 'langbot-brand'] + assert by_id['langbot-brand']['children'] == ['langbot-generated', 'langbot-brand-link'] + assert by_id['langbot-brand']['justify'] == 'spaceBetween' + assert by_id['langbot-generated']['text'] == 'AI-generated' + assert by_id['langbot-generated']['variant'] == 'caption' + assert by_id['langbot-brand-link']['text'] == 'LangBot' + assert by_id['langbot-brand-link']['variant'] == 'caption' + assert by_id['langbot-brand-link']['icon']['url'] == 'https://langbot.app/logo-blue.png' + assert by_id['langbot-brand-link']['onLinkClick']['functionCall'] == { + 'call': 'openUrl', + 'args': {'url': 'https://langbot.app?utm_source=dingtalk&utm_medium=bot_card&utm_campaign=langbot'}, + } assert update_text_card_messages('surface-id', 'done')[0]['updateDataModel']['path'] == '/content' @@ -57,7 +61,7 @@ async def test_create_card_for_target_uses_robot_a2ui_delivery(): request = client.create_and_deliver_ai_card.await_args.kwargs assert request['open_space_id'] == 'dtv1.card//im_robot.user-1' assert request['is_group'] is False - assert request['a2ui_messages'][2]['updateComponents']['components'][0]['children'][0] == 'langbot-brand' + assert request['a2ui_messages'][2]['updateComponents']['components'][0]['children'][-1] == 'langbot-brand' @pytest.mark.asyncio diff --git a/tests/unit_tests/platform/test_dingtalk_eba_adapter.py b/tests/unit_tests/platform/test_dingtalk_eba_adapter.py index 3009e70d9..adcebc88e 100644 --- a/tests/unit_tests/platform/test_dingtalk_eba_adapter.py +++ b/tests/unit_tests/platform/test_dingtalk_eba_adapter.py @@ -357,7 +357,7 @@ async def test_dingtalk_interaction_delivery_and_callback_event(): components = kwargs['a2ui_messages'][2]['updateComponents']['components'] button = next(component for component in components if component['component'] == 'Button') assert button['action']['event']['context']['actionId'] == 'lbi:callback-token:a:0' - assert components[0]['children'][0] == 'langbot-brand' + assert components[0]['children'][-1] == 'langbot-brand' assert any(component['id'] == 'langbot-brand-link' for component in components) native = dingtalk_card_callback_event(