test/agent/test_task_deprecation.py
Rama main · réplica de lectura del repositorio original.
# Copyright (c) 2026, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
#
# SPDX-License-Identifier: Apache-2.0
import warnings
from pathlib import Path
from typing import Any
import pytest
from dirty_equals import HasAttributes, IsInstance, IsStr
from ag2 import Agent, Context, TaskInject
from ag2.events import BaseEvent, TaskCompleted, TaskFailed, TaskStarted, ToolCallEvent
from ag2.stream import MemoryStream
from ag2.task import Task, TaskSpec, TaskState
from ag2.testing import TestConfig
DEPRECATION = r"Agent\.task\(\) is deprecated and will be removed in 1\.4\.0"
class Checkpoints:
def __init__(self) -> None:
self.states: dict[str, dict[str, Any]] = {"prior": {"next_document": 12}}
async def read(self, task_id: str) -> dict[str, Any] | None:
return self.states.get(task_id)
async def write(self, task_id: str, state: dict[str, Any]) -> None:
self.states[task_id] = state
async def report_progress(task: TaskInject) -> str:
"""Report progress on the caller's task."""
if task is not None:
await task.progress({"from_tool": True})
return "ok"
def task_events(events: list[BaseEvent]) -> list[BaseEvent]:
return [event for event in events if isinstance(event, (TaskStarted, TaskCompleted, TaskFailed))]
def legacy_task(agent: Agent, payload: dict[str, Any], context: Context, store: Checkpoints) -> Task:
with pytest.warns(DeprecationWarning, match=DEPRECATION) as records:
task = agent.task(
"index documents",
description="resume indexing",
payload=payload,
capability="indexing",
context=context,
ttl_seconds=60,
checkpoint_store=store,
resume_from="prior",
)
[record] = records
# The warning points at the user's call site, not at the framework.
assert Path(record.filename) == Path(__file__)
return task
def direct_task(agent: Agent, payload: dict[str, Any], context: Context, store: Checkpoints) -> Task:
return Task(
owner_id=agent.name,
spec=TaskSpec(
title="index documents",
description="resume indexing",
payload=dict(payload),
capability="indexing",
),
context=context,
ttl_seconds=60,
checkpoint_store=store,
resume_from="prior",
)
@pytest.mark.asyncio
@pytest.mark.parametrize("build", [direct_task, legacy_task], ids=["direct-task", "deprecated-factory"])
async def test_migrating_to_direct_task_keeps_the_same_behaviour(build: Any) -> None:
agent = Agent("indexer", config=TestConfig(ToolCallEvent(name="report_progress"), "done"), tools=[report_progress])
stream = MemoryStream()
context = Context(stream=stream)
store = Checkpoints()
payload = {"region": "eu"}
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
task = build(agent, payload, context, store)
payload["region"] = "us"
async with task:
resumed = task.resumed_state
await agent.ask("index", stream=stream, dependencies=context.dependencies)
await task.checkpoint({"next_document": 24})
await task.complete({"indexed": 24})
assert resumed == {"next_document": 12}
assert task.metadata.progress == {"from_tool": True}
assert store.states[task.task_id] == {"next_document": 24}
assert task.state == TaskState.COMPLETED
spec = TaskSpec(
title="index documents",
description="resume indexing",
payload={"region": "eu"},
capability="indexing",
)
assert task_events(await stream.history.get_events()) == [
IsInstance(TaskStarted)
& HasAttributes(task_id=task.task_id, agent_name="indexer", spec=spec, expires_at=IsStr()),
IsInstance(TaskCompleted) & HasAttributes(task_id=task.task_id, result={"indexed": 24}),
]
@pytest.mark.asyncio
async def test_deprecated_factory_still_fails_the_task_on_error() -> None:
with pytest.warns(DeprecationWarning, match=DEPRECATION):
task = Agent("worker").task("flaky")
with pytest.raises(ValueError, match="boom"):
async with task:
raise ValueError("boom")
assert task.state == TaskState.FAILED
assert [type(event) for event in await task.context.stream.history.get_events()] == [TaskStarted, TaskFailed]