feat(agentscope): add memory system and automation job support

- Add consumer_registry and pipeline_registry for runtime orchestration
- Add Visibility schema for message filtering
- Add PipelineSpec for agent pipeline configuration
- Add automation job models and configuration
- Remove memory_prompt.py (consolidated into memory system)
- Update runtime components: context_loader, context_service, orchestrator, runner, tasks
- Update toolkit: tool_config, tool_middleware, custom tools (calendar, user_lookup)
- Add auth_helpers and calendar_domain utilities
- Add system_agents.yaml configuration
This commit is contained in:
qzl
2026-03-19 18:42:35 +08:00
parent 0661016827
commit 0abf51e837
55 changed files with 2172 additions and 1233 deletions
@@ -189,3 +189,56 @@ def test_step_started_internal_event_keeps_step_name() -> None:
assert result["type"] == "STEP_STARTED"
assert result["stepName"] == "worker"
def test_run_error_prefers_top_level_message_and_code() -> None:
internal = {
"type": "run.error",
"threadId": "thread-1",
"runId": "run-1",
"message": "runtime failed",
"code": "RUNTIME_ERROR",
"data": {
"message": "nested message",
"code": "NESTED_ERROR",
},
}
result = to_agui_wire_event(internal)
assert result["type"] == "RUN_ERROR"
assert result["message"] == "runtime failed"
assert result["code"] == "RUNTIME_ERROR"
def test_run_error_falls_back_to_data_when_top_level_missing() -> None:
internal = {
"type": "run.error",
"threadId": "thread-1",
"runId": "run-1",
"data": {
"message": "nested message",
"code": "NESTED_ERROR",
},
}
result = to_agui_wire_event(internal)
assert result["type"] == "RUN_ERROR"
assert result["message"] == "nested message"
assert result["code"] == "NESTED_ERROR"
def test_run_error_uses_default_message_when_payload_invalid() -> None:
internal = {
"type": "run.error",
"threadId": "thread-1",
"runId": "run-1",
"data": "invalid",
}
result = to_agui_wire_event(internal)
assert result["type"] == "RUN_ERROR"
assert result["message"] == "Unknown error"
assert "code" not in result
@@ -59,6 +59,16 @@ def _patch_repositories(
monkeypatch.setattr(store_module, "MessageRepository", _FakeMessageRepository)
monkeypatch.setattr(store_module, "AgentChatSessionStatus", _SessionStatus)
async def _fake_stage_bit_map(self, *, session: object) -> dict[str, int]:
del self, session
return {"router": 16, "worker": 17, "memory": 18}
monkeypatch.setattr(
store_module.SqlAlchemyEventStore,
"_load_stage_visibility_bit_map",
_fake_stage_bit_map,
)
@pytest.mark.asyncio
async def test_store_persists_worker_output_with_answer_as_content(
@@ -103,6 +113,7 @@ async def test_store_persists_worker_output_with_answer_as_content(
assert metadata["agent_output"]["answer"] == "worker-answer"
assert metadata["agent_output"]["ui_hints"]["intent"] == "message"
assert append_kwargs["cost"] == Decimal("0.123")
assert append_kwargs["visibility_mask"] == ((1 << 0) | (1 << 17))
assert captured["message_delta"] == 1
assert captured["token_delta"] == 8
@@ -141,3 +152,4 @@ async def test_store_persists_tool_output_with_summary_as_content(
metadata["tool_agent_output"]["result"]
== "status=success batch=1 success=1 failed=0 ids=[event-1]"
)
assert append_kwargs["visibility_mask"] == (1 << 0)