mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-09-27 03:46:39 +08:00
122 lines
4.0 KiB
Python
122 lines
4.0 KiB
Python
"""Shared admission and real embedded artifact schema regressions."""
|
|
|
|
import copy
|
|
import json
|
|
from pathlib import Path
|
|
from types import SimpleNamespace as NS
|
|
|
|
import pytest
|
|
import sqlalchemy as sa
|
|
from tests.unit_tests.api.service.test_pipeline_migration import (
|
|
env as migration_env,
|
|
execute,
|
|
WS,
|
|
SOURCE,
|
|
RID,
|
|
planner,
|
|
)
|
|
from langbot.pkg.agent.runner.interaction_store import InteractionStore, InteractionScopeError
|
|
from langbot.pkg.entity.persistence.agent_interaction import AgentInteraction
|
|
|
|
|
|
@pytest.fixture
|
|
async def env(tmp_path, monkeypatch):
|
|
async for value in migration_env.__wrapped__(tmp_path, monkeypatch):
|
|
yield value
|
|
|
|
|
|
async def request(env, **kwargs):
|
|
return await InteractionStore(env.pm.get_db_engine()).create_request(
|
|
interaction_id='form',
|
|
run_id='run',
|
|
binding_id='binding',
|
|
runner_id=RID,
|
|
processor_type='pipeline',
|
|
processor_id='one',
|
|
workspace_id=WS,
|
|
request={},
|
|
delivery_target={},
|
|
expected_config=copy.deepcopy(SOURCE),
|
|
authority_check=lambda: True,
|
|
**kwargs,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_stale_writer_after_commit_rejected(env):
|
|
original = env.svc._activate
|
|
|
|
async def activate(*args):
|
|
with pytest.raises(InteractionScopeError):
|
|
await request(env)
|
|
return await original(*args)
|
|
|
|
env.svc._activate = activate
|
|
task = await execute(env)
|
|
assert task.task_context.metadata['results'][0]['state'] == 'migrated'
|
|
with pytest.raises(InteractionScopeError):
|
|
await request(env)
|
|
async with env.engine.connect() as conn:
|
|
assert not (await conn.execute(sa.select(AgentInteraction))).all()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_writer_requires_pipeline_authority(env):
|
|
with pytest.raises(InteractionScopeError):
|
|
await InteractionStore(env.engine).create_request(
|
|
interaction_id='form',
|
|
run_id='run',
|
|
binding_id='binding',
|
|
runner_id=RID,
|
|
processor_type='pipeline',
|
|
processor_id='one',
|
|
workspace_id=WS,
|
|
request={},
|
|
delivery_target={},
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize(
|
|
'folder,field,good,bad',
|
|
[
|
|
('LangflowAgent', 'tweaks', {'node': {'value': 1}}, ['not-an-object']),
|
|
('WeKnoraAgent', 'knowledge-base-ids', ['kb-a'], [1]),
|
|
],
|
|
)
|
|
async def test_embedded_artifact_schema_types(env, folder, field, good, bad):
|
|
root = Path(__file__).parent / 'fixtures'
|
|
artifact = 'langflow-agent' if folder == 'LangflowAgent' else 'weknora-agent'
|
|
spec = {'config': json.loads((root / (artifact + '-artifact-schema.json')).read_text())}
|
|
kind = 'json' if folder == 'LangflowAgent' else 'array[string]'
|
|
schema = next(s for s in spec['config'] if s['type'] == kind)
|
|
descriptor = env.ap.runner_registry.list_runners.return_value[0]
|
|
descriptor.config_schema = [schema]
|
|
plan = planner(SOURCE)
|
|
plan['config']['ai']['runner_config'][RID] = {schema['name']: good}
|
|
await env.svc._verify_runtime(NS(workspace_uuid=WS), plan)
|
|
plan['config']['ai']['runner_config'][RID][schema['name']] = bad
|
|
with pytest.raises(env.m.MigrationError, match='runner_schema_incompatible'):
|
|
await env.svc._verify_runtime(NS(workspace_uuid=WS), plan)
|
|
|
|
|
|
def test_conversation_authority_is_captured_before_runner_returns():
|
|
from langbot.pkg.agent.runner.interaction_manager import InteractionManager
|
|
|
|
old, new = NS(), NS()
|
|
config = planner(SOURCE)['config']
|
|
query = NS(pipeline_config=config, pipeline_uuid='one', session=NS(using_conversation=new))
|
|
binding = NS(
|
|
processor_type='pipeline', processor_id='one', runner_id=RID, runner_config=config['ai']['runner_config'][RID]
|
|
)
|
|
authority = InteractionManager._pipeline_admission(
|
|
binding,
|
|
NS(id=RID),
|
|
{
|
|
'_query': query,
|
|
'_pipeline_expected_config': copy.deepcopy(config),
|
|
'_pipeline_conversation': old,
|
|
},
|
|
)
|
|
assert authority['authority_check']() is False
|