mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-19 02:56:17 +00:00
* feat(extensions): expose incremental run evidence reader * fix(extensions): address run evidence review feedback * docs(extensions): clarify run deletion reconciliation * docs(migrations): align current head documentation * fix(extensions): isolate run evidence event reads * test: avoid pinning run change migration to latest head --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
73 lines
2.8 KiB
Python
73 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
|
|
import pytest
|
|
import sqlalchemy as sa
|
|
from alembic import command
|
|
from alembic.script import ScriptDirectory
|
|
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
|
|
|
|
from deerflow.persistence.bootstrap import _MIGRATIONS_DIR, _get_alembic_config
|
|
from deerflow.persistence.run import RunRepository
|
|
|
|
pytestmark = pytest.mark.asyncio
|
|
|
|
REVISION = "0023_run_change_seq"
|
|
PREVIOUS = "0022_scheduled_occurrence_seq"
|
|
|
|
|
|
async def test_changed_run_revision_is_in_single_head_chain():
|
|
script = ScriptDirectory(str(_MIGRATIONS_DIR))
|
|
assert len(script.get_heads()) == 1
|
|
# Later migrations may advance the head without removing this revision.
|
|
assert REVISION in {revision.revision for revision in script.walk_revisions()}
|
|
assert script.get_revision(REVISION).down_revision == PREVIOUS
|
|
|
|
|
|
async def test_upgrade_exposes_legacy_runs_and_allocates_new_positions(tmp_path):
|
|
engine = create_async_engine(f"sqlite+aiosqlite:///{tmp_path / 'migration.db'}")
|
|
cfg = _get_alembic_config(engine)
|
|
try:
|
|
await asyncio.to_thread(command.upgrade, cfg, PREVIOUS)
|
|
async with engine.begin() as connection:
|
|
for run_id in ("legacy-a", "legacy-b"):
|
|
await connection.execute(
|
|
sa.text(
|
|
"INSERT INTO runs "
|
|
"(run_id, thread_id, user_id, status, operation_kind, metadata_json, "
|
|
"kwargs_json, multitask_strategy, message_count, total_input_tokens, "
|
|
"total_output_tokens, total_tokens, llm_call_count, lead_agent_tokens, "
|
|
"subagent_tokens, middleware_tokens, created_at, updated_at) "
|
|
"VALUES (:run_id, :thread_id, 'user-1', 'pending', 'run', '{}', '{}', "
|
|
"'reject', 0, 0, 0, 0, 0, 0, 0, 0, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)"
|
|
),
|
|
{"run_id": run_id, "thread_id": f"thread-{run_id}"},
|
|
)
|
|
|
|
await asyncio.to_thread(command.upgrade, cfg, REVISION)
|
|
factory = async_sessionmaker(engine, expire_on_commit=False)
|
|
repo = RunRepository(factory)
|
|
legacy = await repo.list_changed(
|
|
after_change_seq=-1,
|
|
after_run_id="",
|
|
user_id="user-1",
|
|
limit=10,
|
|
)
|
|
assert [(row["change_seq"], row["run_id"]) for row in legacy] == [
|
|
(0, "legacy-a"),
|
|
(0, "legacy-b"),
|
|
]
|
|
|
|
await repo.update_status("legacy-a", "error")
|
|
changed = await repo.list_changed(
|
|
after_change_seq=0,
|
|
after_run_id="legacy-b",
|
|
user_id="user-1",
|
|
limit=10,
|
|
)
|
|
assert [row["run_id"] for row in changed] == ["legacy-a"]
|
|
assert changed[0]["change_seq"] > 0
|
|
finally:
|
|
await engine.dispose()
|