2026-08-11 06:37:24 +08:00
|
|
|
|
import asyncio
|
2026-08-09 13:50:35 +08:00
|
|
|
|
import json
|
|
|
|
|
|
|
2026-08-11 06:37:24 +08:00
|
|
|
|
from gfa_core.mas.agents.intent_v2 import IntentAgentV2
|
2026-08-09 13:50:35 +08:00
|
|
|
|
from gfa_core.mas.agents.conversation_tools import build_plantai_conversation_tools
|
|
|
|
|
|
from gfa_core.mas.llm import LLMManager
|
|
|
|
|
|
from gfa_core.mas.workflow_models import GoalLedger
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _registry(tmp_path, *, job_id="job-data-preparation-handoff"):
|
|
|
|
|
|
ledger = GoalLedger(
|
|
|
|
|
|
conversation_id="conversation-data-preparation-handoff",
|
|
|
|
|
|
revision=0,
|
|
|
|
|
|
user_terms={
|
|
|
|
|
|
"active_job_id": job_id,
|
|
|
|
|
|
"gene_family": "SPL",
|
|
|
|
|
|
"target_species": ["Ft"],
|
|
|
|
|
|
"reference_species": ["At"],
|
|
|
|
|
|
"config_confirmed": True,
|
|
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
return build_plantai_conversation_tools(
|
|
|
|
|
|
llm_manager=LLMManager({}),
|
|
|
|
|
|
project_root=tmp_path,
|
|
|
|
|
|
bound_job_id=job_id,
|
|
|
|
|
|
goal_ledger=ledger,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_analysis_handoff_is_not_rewritten_to_genome_prepare(tmp_path):
|
|
|
|
|
|
resolved = _registry(tmp_path).resolve_analysis_handoff_request(
|
|
|
|
|
|
"执行亚家族分类",
|
|
|
|
|
|
workflow_id="gene_family",
|
|
|
|
|
|
guidance=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert resolved.startswith("执行亚家族分类\n")
|
|
|
|
|
|
assert "执行数据准备(genome_prepare)" not in resolved
|
|
|
|
|
|
assert "目标物种 Ft" in resolved
|
|
|
|
|
|
assert "参考物种 At" in resolved
|
|
|
|
|
|
assert "正式 config.xlsx 已确认" in resolved
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_genome_prepare_manifest_does_not_change_analysis_handoff(tmp_path):
|
|
|
|
|
|
job_id = "job-manifest-independent-handoff"
|
|
|
|
|
|
registry = _registry(tmp_path, job_id=job_id)
|
|
|
|
|
|
before = registry.resolve_analysis_handoff_request(
|
|
|
|
|
|
"执行亚家族分类",
|
|
|
|
|
|
workflow_id="gene_family",
|
|
|
|
|
|
guidance=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
final_dir = tmp_path / "workspace" / job_id / "final"
|
|
|
|
|
|
final_dir.mkdir(parents=True)
|
|
|
|
|
|
(final_dir / "genome_prepare.genome_prepare.manifest.json").write_text(
|
|
|
|
|
|
json.dumps({"stage": "genome_prepare", "status": "success"}),
|
|
|
|
|
|
encoding="utf-8",
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
after = registry.resolve_analysis_handoff_request(
|
|
|
|
|
|
"执行亚家族分类",
|
|
|
|
|
|
workflow_id="gene_family",
|
|
|
|
|
|
guidance=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert after == before
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_explicit_data_preparation_request_is_preserved(tmp_path):
|
|
|
|
|
|
resolved = _registry(tmp_path).resolve_analysis_handoff_request(
|
|
|
|
|
|
"执行数据准备",
|
|
|
|
|
|
workflow_id="data_preparation",
|
|
|
|
|
|
guidance=False,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert resolved.startswith("执行数据准备\n")
|
|
|
|
|
|
assert "当前业务动作已由数据准备契约唯一确定" not in resolved
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_next_step_question_is_not_rewritten_to_genome_prepare(tmp_path):
|
|
|
|
|
|
resolved = _registry(tmp_path).resolve_analysis_handoff_request(
|
|
|
|
|
|
"接下来需要做什么?",
|
|
|
|
|
|
workflow_id="gene_family",
|
|
|
|
|
|
guidance=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert resolved.startswith("接下来需要做什么?\n")
|
|
|
|
|
|
assert "执行数据准备(genome_prepare)" not in resolved
|
2026-08-11 06:37:24 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_bound_analysis_intent_uses_default_language(monkeypatch, tmp_path):
|
|
|
|
|
|
captured_queries = []
|
|
|
|
|
|
|
|
|
|
|
|
async def fake_execute(_self, state, message):
|
|
|
|
|
|
captured_queries.append(message.payload["query"])
|
|
|
|
|
|
state.results["results"] = {
|
|
|
|
|
|
"intent": {
|
|
|
|
|
|
"gene_family": "SPL",
|
|
|
|
|
|
"stages": ["ppi", "kaks"],
|
|
|
|
|
|
"primary_stage": "ppi",
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return state
|
|
|
|
|
|
|
|
|
|
|
|
monkeypatch.setattr(IntentAgentV2, "execute", fake_execute)
|
|
|
|
|
|
result = json.loads(
|
|
|
|
|
|
asyncio.run(
|
|
|
|
|
|
_registry(tmp_path).dispatch(
|
|
|
|
|
|
"recognize_analysis_intent",
|
|
|
|
|
|
json.dumps({"query": "执行Ft的PPI和kaks分析"}, ensure_ascii=False),
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert result["ok"] is True
|
|
|
|
|
|
assert result["data"]["stages"] == ["ppi", "kaks"]
|
|
|
|
|
|
assert captured_queries[0].startswith("执行Ft的PPI和kaks分析\n")
|