2026-09-03 21:28:19 +08:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import asyncio
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
from server.agent_core.intent import parse_fast
|
|
|
|
|
from server.aps_domain.workflow import handle_intent
|
|
|
|
|
from server.state.packs import load_pack, resolve_pack_reference
|
|
|
|
|
from server.state.store import WorldStore
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PACK_PATH = Path(__file__).resolve().parents[2] / "server" / "data" / "packs" / "optimize-simulation-v1.json"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_chat_command_parses_data_pack_and_algorithm_slots():
|
|
|
|
|
world = load_pack(str(PACK_PATH))
|
|
|
|
|
|
|
|
|
|
result = parse_fast(
|
|
|
|
|
"使用 Optimize synthetic debug V1 数据用 EDD 算法生成排产方案",
|
|
|
|
|
world,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert result is not None
|
|
|
|
|
assert result.intent == "flex.schedule"
|
|
|
|
|
assert result.params["dataPackRef"] == "Optimize synthetic debug V1"
|
|
|
|
|
assert result.params["engine"] == "OPTIMIZE"
|
|
|
|
|
assert result.params["sortMode"] == "EDD"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_pack_reference_resolves_registered_aliases():
|
|
|
|
|
pack = resolve_pack_reference("Optimize 模拟数据")
|
|
|
|
|
|
|
|
|
|
assert pack is not None
|
|
|
|
|
assert pack["file"] == "optimize-simulation-v1.json"
|
|
|
|
|
|
|
|
|
|
|
2026-09-03 22:24:48 +08:00
|
|
|
def test_chat_command_parses_directory_file_and_algorithm_slots():
|
|
|
|
|
result = parse_fast(
|
|
|
|
|
r"使用 D:\aps-data 目录下的 orders.xlsx 数据用 EDD 算法生成排产方案",
|
|
|
|
|
{},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert result is not None
|
|
|
|
|
assert result.intent == "flex.schedule"
|
|
|
|
|
assert result.params["dataDir"] == r"D:\aps-data"
|
|
|
|
|
assert result.params["dataFile"] == "orders.xlsx"
|
|
|
|
|
assert result.params["dataPath"].endswith(r"aps-data\orders.xlsx")
|
|
|
|
|
assert result.params["sortMode"] == "EDD"
|
|
|
|
|
assert result.params["engine"] == "OPTIMIZE"
|
|
|
|
|
|
|
|
|
|
|
2026-09-03 21:28:19 +08:00
|
|
|
def test_chat_command_loads_pack_and_materializes_optimize_result(tmp_path, monkeypatch):
|
|
|
|
|
monkeypatch.setenv("APS_DB_DISABLED", "1")
|
|
|
|
|
store = WorldStore(path=str(tmp_path / "world.json"))
|
|
|
|
|
intent = parse_fast(
|
|
|
|
|
"使用 Optimize synthetic debug V1 数据用 EDD 算法生成排产方案",
|
|
|
|
|
store.data,
|
|
|
|
|
)
|
|
|
|
|
assert intent is not None
|
|
|
|
|
|
|
|
|
|
reply = asyncio.run(handle_intent(store, "round88", intent, actor="test"))
|
|
|
|
|
|
|
|
|
|
assert "Optimize" in reply.text
|
|
|
|
|
assert "Optimize synthetic debug V1" in reply.text
|
|
|
|
|
block = next(block for block in reply.blocks if block.type == "flex-schedule")
|
|
|
|
|
assert block.props["dataPack"]["file"] == "optimize-simulation-v1.json"
|
|
|
|
|
assert block.props["algorithm"]["rule"] == "EDD"
|
|
|
|
|
assert block.props["stats"]["vlCount"] == 10
|
|
|
|
|
assert block.props["stats"]["woCount"] == 72
|
|
|
|
|
assert store.data["flexScheduleVersions"][-1]["engineType"] == "OPTIMIZE"
|
|
|
|
|
assert store.data["flexScheduleVersions"][-1]["algorithmId"] == "optimize.edd"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_unknown_pack_fails_closed_without_creating_schedule(tmp_path, monkeypatch):
|
|
|
|
|
monkeypatch.setenv("APS_DB_DISABLED", "1")
|
|
|
|
|
store = WorldStore(path=str(tmp_path / "world.json"))
|
|
|
|
|
intent = parse_fast("使用不存在的数据,用 EDD 算法生成排产方案", store.data)
|
|
|
|
|
assert intent is not None
|
|
|
|
|
|
|
|
|
|
reply = asyncio.run(handle_intent(store, "round88", intent, actor="test"))
|
|
|
|
|
|
|
|
|
|
assert "找不到数据包" in reply.text
|
|
|
|
|
assert not store.data.get("flexScheduleVersions")
|
2026-09-03 22:24:48 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_unreadable_directory_fails_closed_without_scheduling(tmp_path, monkeypatch):
|
|
|
|
|
monkeypatch.setenv("APS_DB_DISABLED", "1")
|
|
|
|
|
store = WorldStore(path=str(tmp_path / "world.json"))
|
|
|
|
|
intent = parse_fast(
|
|
|
|
|
r"使用 D:\missing-aps-data 目录下的 orders.xlsx 数据用 EDD 算法生成排产方案",
|
|
|
|
|
store.data,
|
|
|
|
|
)
|
|
|
|
|
assert intent is not None
|
|
|
|
|
|
|
|
|
|
reply = asyncio.run(handle_intent(store, "round88", intent, actor="test"))
|
|
|
|
|
|
|
|
|
|
assert "数据文件不存在" in reply.text or "数据目录不存在" in reply.text
|
|
|
|
|
assert not store.data.get("flexScheduleVersions")
|