feat(n7web): refine spatial UI and NFC-gated extension routing

This commit is contained in:
Miayui
2026-09-16 16:14:10 +08:00
parent 0e4328f548
commit 75ce391312
16 changed files with 925 additions and 106 deletions
+78
View File
@@ -696,6 +696,84 @@ class SelfExtensionTests(unittest.TestCase):
self.assertEqual(changed["device_id"], "toy-light-v2")
self.assertEqual(service.list_peripheral_capabilities(), [])
def test_new_structured_slot_is_parseable_before_nfc_authorization(self) -> None:
with TemporaryDirectory() as directory:
service = SelfExtensionService(
SimulationGateway(),
catalog_db_path=Path(directory, "infrared-slots.sqlite3"),
)
service.save_infrared_slot(
11,
{
"device_id": "toy-cacti-002",
"object_names": ["仙人掌"],
"action_names": ["打开", "开启"],
"source": "tcp",
},
)
self.assertEqual(service.list_peripheral_capabilities(), [])
routing = service.list_peripheral_routing_capabilities()
self.assertEqual(len(routing), 1)
self.assertEqual(routing[0]["id"], "ir-slot:toy-cacti-002:11")
self.assertEqual(routing[0]["authorization_state"], "nfc_binding_required")
self.assertTrue(routing[0]["parseable"])
self.assertFalse(routing[0]["execution_authorized"])
partition = partition_active_peripheral_intent(
"开启仙人掌",
routing,
{"card": None},
)
self.assertEqual(partition["peripheral_actions"], [])
self.assertEqual(partition["residual_utterance"], "")
self.assertEqual(partition["unresolved_peripheral_clauses"], [])
self.assertEqual(
[
(
item["capability"]["id"],
item["capability"]["slot"],
item["reason"],
)
for item in partition["denied_peripheral_actions"]
],
[("ir-slot:toy-cacti-002:11", 11, "nfc_binding_required")],
)
self.assertIsNone(
resolve_active_peripheral_command(
"开启仙人掌",
routing,
{"card": None},
)
)
service.sync_peripheral_catalog(
[
{
**routing[0],
"enabled": True,
"card_uid": "DBA5B203",
}
]
)
authorized_routing = service.list_peripheral_routing_capabilities()
self.assertEqual(
authorized_routing[0]["authorization_state"], "authorized"
)
authorized = partition_active_peripheral_intent(
"开启仙人掌",
authorized_routing,
{"card": None},
)
self.assertEqual(
[item["capability"]["slot"] for item in authorized["peripheral_actions"]],
[11],
)
self.assertEqual(authorized["denied_peripheral_actions"], [])
service.delete_infrared_slot(11)
self.assertEqual(service.list_peripheral_routing_capabilities(), [])
def test_structured_slot_rejects_invalid_or_missing_device_id(self) -> None:
with TemporaryDirectory() as directory:
service = SelfExtensionService(