feat: integrate production cockpit AI assistant

This commit is contained in:
vee
2026-09-08 17:46:07 +08:00
parent 5e228e12ae
commit 93103c2579
66 changed files with 11046 additions and 374 deletions
@@ -30,7 +30,7 @@ MAX_PLAN_REQUESTS = 12
MAX_PLAN_PARAMETERS = 12
_OPERATIONS = frozenset({"activate", "deactivate", "increase", "decrease", "set", "save", "apply"})
_SCENE_COMPOSABLE_CAPABILITIES = frozenset(
SCENE_COMPOSABLE_CAPABILITIES = frozenset(
{
"seat.set_longitudinal_position",
"seat.set_cushion_tilt",
@@ -68,12 +68,18 @@ _SCENE_COMPOSABLE_CAPABILITIES = frozenset(
# particular, fan level 0 is a virtual shorthand for "off", while the native
# operation is explicitly 1-7; changing it to HVAC power-off here would alter
# the model's proposed intent.
_SCENE_PARAMETER_BOUNDS: dict[tuple[str, str], tuple[float | None, float | None]] = {
SCENE_PARAMETER_BOUNDS: dict[tuple[str, str], tuple[float | None, float | None]] = {
("climate.set_fan_level", "level"): (1, 7),
}
_ROOT_FIELDS = frozenset(
{"detected_domains", "requests", "ambiguities", "decision_summary", "confidence"}
)
_OPTIONAL_ROOT_FIELDS = frozenset({"metadata"})
_SCENE_TEMPLATE_METADATA_FIELDS = frozenset(
{"source", "template_id", "template_revision"}
)
_SCENE_TEMPLATE_ID = re.compile(r"^[a-z0-9][a-z0-9_-]{0,63}$")
_SCENE_TEMPLATE_REVISION = re.compile(r"^[a-f0-9]{16}$")
_REQUEST_FIELDS = frozenset(
{
"domain",
@@ -540,7 +546,7 @@ def _scene_contract_error(
return f"参数 {name} 的类型必须是 {expected_type}"
minimum = spec.get("minimum")
maximum = spec.get("maximum")
scene_bounds = _SCENE_PARAMETER_BOUNDS.get((capability, name))
scene_bounds = SCENE_PARAMETER_BOUNDS.get((capability, name))
if scene_bounds is not None:
minimum, maximum = scene_bounds
if numeric and (
@@ -1090,7 +1096,11 @@ def guard_assistant_plan(
or the user's explicit save confirmation.
"""
if not isinstance(raw_plan, Mapping) or set(raw_plan) != _ROOT_FIELDS:
if (
not isinstance(raw_plan, Mapping)
or not _ROOT_FIELDS.issubset(raw_plan)
or set(raw_plan) - _ROOT_FIELDS - _OPTIONAL_ROOT_FIELDS
):
raise ValueError("assistant plan must be a structured intent object")
try:
encoded = json.dumps(raw_plan, ensure_ascii=False, allow_nan=False).encode("utf-8")
@@ -1099,6 +1109,29 @@ def guard_assistant_plan(
if len(encoded) > MAX_PLAN_BYTES:
raise ValueError("assistant plan is too large")
plan_metadata: dict[str, str] | None = None
if "metadata" in raw_plan:
raw_metadata = raw_plan.get("metadata")
if (
not isinstance(raw_metadata, Mapping)
or set(raw_metadata) != _SCENE_TEMPLATE_METADATA_FIELDS
or raw_metadata.get("source") != "scene_template"
or not _SCENE_TEMPLATE_ID.fullmatch(
str(raw_metadata.get("template_id") or "")
)
or not _SCENE_TEMPLATE_REVISION.fullmatch(
str(raw_metadata.get("template_revision") or "")
)
):
raise ValueError("assistant plan metadata is invalid")
if not allow_scene_composition:
raise ValueError("assistant plan metadata is only valid for scene composition")
plan_metadata = {
"source": "scene_template",
"template_id": str(raw_metadata["template_id"]),
"template_revision": str(raw_metadata["template_revision"]),
}
requests = raw_plan.get("requests", [])
if not isinstance(requests, Sequence) or isinstance(requests, (str, bytes, bytearray)):
raise ValueError("assistant plan requests must be an array") # noqa: TRY004
@@ -1155,7 +1188,7 @@ def guard_assistant_plan(
}
)
continue
if allow_scene_composition and capability not in _SCENE_COMPOSABLE_CAPABILITIES:
if allow_scene_composition and capability not in SCENE_COMPOSABLE_CAPABILITIES:
rejected.append(
{
"field": f"requests[{index}].capability",
@@ -1320,9 +1353,11 @@ def guard_assistant_plan(
"detected_domains": detected_domains,
"requests": accepted,
"ambiguities": [*rejected],
"decision_summary": decision_summary or ["Codex 计划已通过原始请求能力约束。"],
"decision_summary": decision_summary or ["小迪生成的计划已通过原始请求能力约束。"],
"confidence": confidence,
}
if plan_metadata is not None:
normalized["metadata"] = plan_metadata
return GuardedAssistantPlan(normalized, tuple(rejected))
@@ -1330,6 +1365,8 @@ __all__ = [
"MAX_PLAN_BYTES",
"MAX_PLAN_PARAMETERS",
"MAX_PLAN_REQUESTS",
"SCENE_COMPOSABLE_CAPABILITIES",
"SCENE_PARAMETER_BOUNDS",
"GuardedAssistantPlan",
"guard_assistant_plan",
]