mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-11-03 22:32:27 +08:00
Merge remote-tracking branch 'origin/master' into fix/memory-fact-integrity
This commit is contained in:
@@ -284,13 +284,16 @@ class RunnerContextBuilder:
|
||||
and identity.bot_id == event.bot_id
|
||||
and identity.pipeline_id == (binding.processor_id or binding.agent_id)
|
||||
):
|
||||
# Query-backed platform events carry a Host-owned launcher
|
||||
# Query-backed platform events carry a Host-owned entry-session
|
||||
# identity even when the event-first conversation UUID changes
|
||||
# after create_new_conversation(). Keep it separate from the
|
||||
# protocol conversation UUID so reset-sensitive plugins can use
|
||||
# a stable session key.
|
||||
stable_launcher_type = identity.session_launcher_type or identity.query_launcher_type
|
||||
stable_launcher_id = identity.session_launcher_id or identity.query_launcher_id
|
||||
# after create_new_conversation(). This is a Core context
|
||||
# contract: session_id is reset-stable while conversation_id
|
||||
# remains the current Host conversation UUID.
|
||||
stable_launcher_type = identity.session_launcher_type
|
||||
stable_launcher_id = identity.session_launcher_id
|
||||
if stable_launcher_type not in ('group', 'person') or not stable_launcher_id:
|
||||
stable_launcher_type = identity.query_launcher_type
|
||||
stable_launcher_id = identity.query_launcher_id
|
||||
if stable_launcher_type in ('group', 'person') and stable_launcher_id:
|
||||
conversation['session_id'] = f'{stable_launcher_type}_{stable_launcher_id}'
|
||||
if (
|
||||
|
||||
@@ -62,6 +62,34 @@ async def test_exact_native_identity_survives_serialization(mock_query, runner,
|
||||
assert context['conversation']['sender_id'] == 'sender-123'
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_event_first_context_exposes_reset_stable_entry_session_identity(mock_query):
|
||||
mock_query.launcher_type.value = 'group'
|
||||
mock_query.launcher_id = 'event-007'
|
||||
mock_query.session.launcher_type.value = 'person'
|
||||
mock_query.session.launcher_id = 'session-008'
|
||||
event = AgentEventEnvelope.model_validate_json(QueryEntryAdapter.query_to_event(mock_query).model_dump_json())
|
||||
|
||||
context, _ = await build(event, 'ACPAgentRunner', 'sender')
|
||||
|
||||
assert context['conversation']['conversation_id'] == 'conv-uuid-123'
|
||||
assert context['conversation']['session_id'] == 'person_session-008'
|
||||
assert context['conversation']['launcher_type'] is None
|
||||
assert context['conversation']['launcher_id'] is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_entry_session_identity_falls_back_to_query_launcher(mock_query):
|
||||
mock_query.launcher_type.value = 'group'
|
||||
mock_query.launcher_id = 'event-007'
|
||||
mock_query.session.launcher_id = None
|
||||
event = AgentEventEnvelope.model_validate_json(QueryEntryAdapter.query_to_event(mock_query).model_dump_json())
|
||||
|
||||
context, _ = await build(event, 'ACPAgentRunner', 'sender')
|
||||
|
||||
assert context['conversation']['session_id'] == 'group_event-007'
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize('runner', ['DifyAgent', 'N8nAgent', 'CozeAgent'])
|
||||
async def test_missing_authoritative_fields_never_fall_back_to_raw_data(mock_query, runner):
|
||||
@@ -72,6 +100,7 @@ async def test_missing_authoritative_fields_never_fall_back_to_raw_data(mock_que
|
||||
event.data.update({'launcher_type': 'group', 'launcher_id': 'spoof'})
|
||||
context, _ = await build(event, runner)
|
||||
assert context['conversation']['launcher_id'] is None
|
||||
assert context['conversation']['session_id'] is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -91,6 +120,7 @@ async def test_provenance_cannot_cross_scope(mock_query, field):
|
||||
setattr(event, field, 'different')
|
||||
context, _ = await build(event, 'DifyAgent')
|
||||
assert context['conversation']['launcher_id'] is None
|
||||
assert context['conversation']['session_id'] is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -99,6 +129,7 @@ async def test_provenance_cannot_cross_pipeline(mock_query):
|
||||
event.legacy_identity.pipeline_id = 'other-pipeline'
|
||||
context, _ = await build(event, 'DifyAgent')
|
||||
assert context['conversation']['launcher_id'] is None
|
||||
assert context['conversation']['session_id'] is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
Reference in New Issue
Block a user