mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-15 08:56:07 +00:00
feat: Add missing completed input lines handling in DingTalk adapter
This commit is contained in:
@@ -301,6 +301,16 @@ def _dingtalk_completed_input_lines(form_data: dict) -> list[str]:
|
|||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def _dingtalk_missing_completed_input_lines(form_data: dict, form_content: str) -> list[str]:
|
||||||
|
"""Return completed values that are not already rendered in the form body."""
|
||||||
|
rendered_lines = {
|
||||||
|
line.strip()
|
||||||
|
for line in re.split(r'<br\s*/?>|\r?\n', str(form_content or ''), flags=re.IGNORECASE)
|
||||||
|
if line.strip()
|
||||||
|
}
|
||||||
|
return [line for line in _dingtalk_completed_input_lines(form_data) if line.strip() not in rendered_lines]
|
||||||
|
|
||||||
|
|
||||||
def _dingtalk_supports_native_field(form_data: dict) -> bool:
|
def _dingtalk_supports_native_field(form_data: dict) -> bool:
|
||||||
current_name = str(form_data.get('_current_input_field') or '').strip()
|
current_name = str(form_data.get('_current_input_field') or '').strip()
|
||||||
if not current_name or form_data.get('_action_select_only'):
|
if not current_name or form_data.get('_action_select_only'):
|
||||||
@@ -439,6 +449,8 @@ def _dingtalk_extract_component_inputs(params: dict) -> dict:
|
|||||||
elif input_result not in (None, ''):
|
elif input_result not in (None, ''):
|
||||||
input_value = input_result
|
input_value = input_result
|
||||||
if input_value not in (None, ''):
|
if input_value not in (None, ''):
|
||||||
|
if isinstance(input_value, str):
|
||||||
|
input_value = input_value.strip()
|
||||||
result['input'] = input_value
|
result['input'] = input_value
|
||||||
|
|
||||||
select_value = params.get('select')
|
select_value = params.get('select')
|
||||||
@@ -451,6 +463,8 @@ def _dingtalk_extract_component_inputs(params: dict) -> dict:
|
|||||||
if isinstance(select_value, dict):
|
if isinstance(select_value, dict):
|
||||||
select_value = select_value.get('value') or select_value.get('label') or select_value.get('index')
|
select_value = select_value.get('value') or select_value.get('label') or select_value.get('index')
|
||||||
if select_value not in (None, ''):
|
if select_value not in (None, ''):
|
||||||
|
if isinstance(select_value, str):
|
||||||
|
select_value = select_value.strip()
|
||||||
result['select'] = select_value
|
result['select'] = select_value
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@@ -948,9 +962,9 @@ class DingTalkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
|
|||||||
parts.append(f'**{node_title}**')
|
parts.append(f'**{node_title}**')
|
||||||
if form_content:
|
if form_content:
|
||||||
parts.append(_dingtalk_card_markdown(form_content))
|
parts.append(_dingtalk_card_markdown(form_content))
|
||||||
completed_lines = _dingtalk_completed_input_lines(form_data)
|
missing_completed_lines = _dingtalk_missing_completed_input_lines(form_data, form_content)
|
||||||
if completed_lines and not all(line in form_content for line in completed_lines):
|
if missing_completed_lines:
|
||||||
parts.append('<hr>' + '<br>'.join(completed_lines))
|
parts.append('<hr>' + '<br>'.join(missing_completed_lines))
|
||||||
input_hint_lines = [] if native_field else _dingtalk_input_hint_lines(form_data)
|
input_hint_lines = [] if native_field else _dingtalk_input_hint_lines(form_data)
|
||||||
if input_hint_lines:
|
if input_hint_lines:
|
||||||
parts.append('Fill these fields in chat before choosing an action:<br>' + '<br>'.join(input_hint_lines))
|
parts.append('Fill these fields in chat before choosing an action:<br>' + '<br>'.join(input_hint_lines))
|
||||||
@@ -1048,9 +1062,9 @@ class DingTalkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
|
|||||||
parts.append(f'**{node_title}**')
|
parts.append(f'**{node_title}**')
|
||||||
if form_content:
|
if form_content:
|
||||||
parts.append(_dingtalk_card_markdown(form_content))
|
parts.append(_dingtalk_card_markdown(form_content))
|
||||||
completed_lines = _dingtalk_completed_input_lines(form_data)
|
missing_completed_lines = _dingtalk_missing_completed_input_lines(form_data, form_content)
|
||||||
if completed_lines and not all(line in form_content for line in completed_lines):
|
if missing_completed_lines:
|
||||||
parts.append('<hr>' + '<br>'.join(completed_lines))
|
parts.append('<hr>' + '<br>'.join(missing_completed_lines))
|
||||||
input_hint_lines = [] if native_field else _dingtalk_input_hint_lines(form_data)
|
input_hint_lines = [] if native_field else _dingtalk_input_hint_lines(form_data)
|
||||||
if input_hint_lines:
|
if input_hint_lines:
|
||||||
parts.append('Fill these fields in chat before choosing an action:<br>' + '<br>'.join(input_hint_lines))
|
parts.append('Fill these fields in chat before choosing an action:<br>' + '<br>'.join(input_hint_lines))
|
||||||
@@ -1486,14 +1500,15 @@ class DingTalkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
|
|||||||
parts.append(f'**{node_title}**')
|
parts.append(f'**{node_title}**')
|
||||||
if form_content:
|
if form_content:
|
||||||
parts.append(_dingtalk_card_markdown(form_content))
|
parts.append(_dingtalk_card_markdown(form_content))
|
||||||
completed_lines = _dingtalk_completed_input_lines(
|
missing_completed_lines = _dingtalk_missing_completed_input_lines(
|
||||||
{
|
{
|
||||||
'input_defs': input_defs or [],
|
'input_defs': input_defs or [],
|
||||||
'inputs': inputs or {},
|
'inputs': inputs or {},
|
||||||
}
|
},
|
||||||
|
form_content,
|
||||||
)
|
)
|
||||||
if completed_lines and not all(line in form_content for line in completed_lines):
|
if missing_completed_lines:
|
||||||
parts.append('<hr>' + '<br>'.join(completed_lines))
|
parts.append('<hr>' + '<br>'.join(missing_completed_lines))
|
||||||
parts.append(f'<hr>✅ {action_title}')
|
parts.append(f'<hr>✅ {action_title}')
|
||||||
content = '<br><br>'.join(parts)
|
content = '<br><br>'.join(parts)
|
||||||
if self.ap is not None:
|
if self.ap is not None:
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from langbot.pkg.platform.sources.dingtalk import (
|
|||||||
_dingtalk_completed_input_lines,
|
_dingtalk_completed_input_lines,
|
||||||
_dingtalk_extract_component_inputs,
|
_dingtalk_extract_component_inputs,
|
||||||
_dingtalk_form_component_params,
|
_dingtalk_form_component_params,
|
||||||
|
_dingtalk_missing_completed_input_lines,
|
||||||
_dingtalk_pending_input_defs,
|
_dingtalk_pending_input_defs,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -64,6 +65,17 @@ def test_dingtalk_extract_input_and_select_together():
|
|||||||
assert inputs == {'input': 'looks good', 'select': 'A'}
|
assert inputs == {'input': 'looks good', 'select': 'A'}
|
||||||
|
|
||||||
|
|
||||||
|
def test_dingtalk_extract_component_inputs_strips_card_line_endings():
|
||||||
|
inputs = _dingtalk_extract_component_inputs(
|
||||||
|
{
|
||||||
|
'inputResult': {'value': '回复我测试\r\n'},
|
||||||
|
'selectResult': {'value': '1\r'},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert inputs == {'input': '回复我测试', 'select': '1'}
|
||||||
|
|
||||||
|
|
||||||
def test_dingtalk_pending_input_defs_includes_file_fields():
|
def test_dingtalk_pending_input_defs_includes_file_fields():
|
||||||
pending = _dingtalk_pending_input_defs(
|
pending = _dingtalk_pending_input_defs(
|
||||||
{
|
{
|
||||||
@@ -96,6 +108,28 @@ def test_dingtalk_completed_input_lines_include_text_and_select_values():
|
|||||||
assert lines == ['✅ comment:looks good', '✅ choice:B']
|
assert lines == ['✅ comment:looks good', '✅ choice:B']
|
||||||
|
|
||||||
|
|
||||||
|
def test_dingtalk_completed_inputs_are_not_repeated_when_already_interleaved():
|
||||||
|
form_data = {
|
||||||
|
'all_input_defs': [
|
||||||
|
{'output_variable_name': 'us_input', 'type': 'paragraph'},
|
||||||
|
{'output_variable_name': 'xiala', 'type': 'select'},
|
||||||
|
],
|
||||||
|
'inputs': {'us_input': '回复我测试\r', 'xiala': '1'},
|
||||||
|
}
|
||||||
|
form_content = '你好\n请输入你的问题\n✅ us_input:回复我测试\n请选择你的答案\n✅ xiala:1'
|
||||||
|
|
||||||
|
assert _dingtalk_missing_completed_input_lines(form_data, form_content) == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_dingtalk_completed_inputs_are_appended_when_template_does_not_render_them():
|
||||||
|
form_data = {
|
||||||
|
'all_input_defs': [{'output_variable_name': 'comment', 'type': 'paragraph'}],
|
||||||
|
'inputs': {'comment': 'ready'},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert _dingtalk_missing_completed_input_lines(form_data, 'Please review') == ['✅ comment:ready']
|
||||||
|
|
||||||
|
|
||||||
def test_dingtalk_clean_form_content_uses_all_input_defs():
|
def test_dingtalk_clean_form_content_uses_all_input_defs():
|
||||||
content = _dingtalk_clean_form_content(
|
content = _dingtalk_clean_form_content(
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user