Files
chenlin 0d986f60bd
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
feat: release v1.0.2 LeKiwi 语言控制与网站嵌入
集成服务器托管模型、自然语言移动与有界抓放、内置 LeKiwi URL 导入和双摄像头;同步部署契约与指定域名 iframe 白名单,保留原有物理安全、会话及调用预算防护。

更新 npm 包及锁文件版本、CHANGELOG 与发布文档。提交前 typecheck、120 项定向前端测试和 44 项后端测试通过(3 项可选跳过);真实 v2 云模型抓放仍待单独验收,不包含运行密钥或构建产物。
2026-09-24 15:29:49 +08:00

100 lines
3.3 KiB
Python

import unittest
from decision_server.commands import checked as motion_checked
from decision_server.language_tasks import checked, resolve_target
from decision_server.protocol import (
LANGUAGE_PRECONDITIONS,
LANGUAGE_SKILLS,
VERSION,
DecisionError,
validate_jev,
validate_plan,
)
from decision_server.protocol import (
LANGUAGE_VERSION as V,
)
def command(**changes):
return (
dict(
version=V,
action="pick_place",
value=0,
summary="搬运方块",
objectId="block",
targetId="B",
position=[],
supportId="table",
)
| changes
)
class LanguageTests(unittest.TestCase):
def test_named_and_coordinates(self):
self.assertEqual(
checked(command(), "抓起方块并搬到B区放下", motion_checked)["targetId"], "B"
)
for text, values in [
("搬到(25,50)厘米", [0.25, 0.5]),
("搬到 X=0.25 Y=0.50 Z=0.128", [0.25, 0.5, 0.128]),
]:
result = checked(command(targetId="coordinates", position=values), text, motion_checked)
self.assertEqual(
resolve_target(result["targetId"], result["position"]),
([0.25, 0.5, 0.128], "table"),
)
def test_bad_targets_and_mismatch(self):
for pos in ([0.8, 0.5], [0.25, 0.5, 0.5], [float("nan"), 0.5]):
with self.assertRaises(DecisionError):
resolve_target("coordinates", pos)
with self.assertRaisesRegex(DecisionError, "command_mismatch"):
checked(
command(targetId="coordinates", position=[0.25, 0.6]),
"搬到(0.25,0.50)",
motion_checked,
)
for text in [
"不要搬到 B 区",
"搬到指定位置",
"前进0.5米然后搬到 B 区",
"搬到 A 区或者 B 区",
]:
self.assertEqual(checked(command(), text, motion_checked)["action"], "clarify")
def test_multiple_or_contradictory_coordinates_rejected(self):
for instruction in ["搬到(0.25,0.5)然后到(0.25,0.6)", "搬到 B 区 (0.25,0.5)"]:
with self.assertRaises(DecisionError):
checked(command(), instruction, motion_checked)
def test_v2_does_not_weaken_v1(self):
plan = dict(
version=V,
objectId="block",
goalId="placement",
summary="计划",
steps=[
dict(skill=s, precondition=LANGUAGE_PRECONDITIONS[s], onFailure="stop")
for s in LANGUAGE_SKILLS
],
)
validate_plan(plan, LANGUAGE_SKILLS, V)
with self.assertRaises(DecisionError):
validate_plan(plan, LANGUAGE_SKILLS, VERSION)
d = dict(
version=V,
choice="stow",
grasp="empty",
diagnosis="none",
recovery="continue",
noul="allow",
score="good",
reason="verified_progress",
)
validate_jev(d, ["stow", "stop"], V)
for field, value in [("noul", "yes"), ("score", 100), ("choice", "carry")]:
with self.assertRaises(DecisionError):
validate_jev(d | {field: value}, ["stow", "stop"], V)