feat(processors): streamline event debugging and run inspection

This commit is contained in:
RockChinQ
2026-09-08 02:30:59 +08:00
parent 237fa6545d
commit ea3e32c904
34 changed files with 1464 additions and 466 deletions
@@ -455,3 +455,20 @@ async def test_processor_instance_history_filters_count_and_pages(store):
)
assert (total, more) == (2, False)
assert second[0]['run_id'] == 'run-0'
@pytest.mark.asyncio
async def test_run_lifecycle_retains_milliseconds(store, monkeypatch):
started = datetime.datetime(2026, 9, 8, 0, 0, 0, 123000, tzinfo=UTC)
monkeypatch.setattr('langbot.pkg.agent.runner.run_ledger_store._utc_now', lambda: started)
run = await store.create_run(
run_id='run-ms', event_id='evt-ms', binding_id='binding-ms', runner_id='runner-ms', status='running'
)
assert run['created_at_ms'] == round(started.timestamp() * 1000)
assert run['started_at_ms'] == run['created_at_ms']
assert run['finished_at_ms'] is None
finished = started + datetime.timedelta(milliseconds=275)
monkeypatch.setattr('langbot.pkg.agent.runner.run_ledger_store._utc_now', lambda: finished)
await store.finalize_run(run_id='run-ms', status='completed')
saved = await store.get_run('run-ms')
assert saved['finished_at_ms'] - saved['started_at_ms'] == 275
@@ -770,6 +770,20 @@ class TestAgentServiceCreateUpdateDelete:
)
async def test_event_processor_can_be_created_before_selecting_a_plugin():
app = _make_app()
service = AgentService(app)
result = await service.create_agent(
WORKSPACE_UUID,
{'kind': 'event_processor', 'name': 'Unconfigured', 'supported_event_patterns': ['*']},
)
values = _compiled_params(app.persistence_mgr.execute_async.call_args.args[0])
assert result['kind'] == 'event_processor'
assert values['component_ref'] is None
assert values['supported_event_patterns'] == []
assert values['config'] == {}
async def test_event_processor_creation_uses_installed_component_scope():
app = _make_app()
ref = 'event_processor:test/welcome/default'
@@ -797,6 +811,34 @@ async def test_event_processor_creation_uses_installed_component_scope():
assert values['config']['runner_config'][ref] == {'greeting': 'Hi'}
async def test_unconfigured_event_processor_can_select_a_plugin_after_creation():
app = _make_app()
row = _agent_row(config={})
row.kind = 'event_processor'
row.component_ref = None
ref = 'event_processor:test/welcome/default'
app.agent_runner_registry = SimpleNamespace(
get=AsyncMock(
return_value=SimpleNamespace(
component_kind='EventProcessor',
supported_event_patterns=['group.member_joined'],
config_schema=[{'name': 'greeting', 'required': True}],
)
)
)
service = AgentService(app)
service._get_agent_row = AsyncMock(return_value=row)
await service.update_agent(
WORKSPACE_UUID,
row.uuid,
{'component_ref': ref, 'parameters': {'greeting': 'Hi'}, 'supported_event_patterns': ['*']},
)
values = _compiled_update_values(app.persistence_mgr.execute_async.call_args.args[0])
assert values['component_ref'] == ref
assert values['supported_event_patterns'] == ['group.member_joined']
assert values['config']['runner_config'][ref] == {'greeting': 'Hi'}
async def test_event_processor_rejects_invalid_component_and_missing_parameters():
app = _make_app()
service = AgentService(app)