Files
q792602257 ca5e300289 fix(semantic-scene): preserve page/intents when all widgets are dangling, drop dead exception-name set
- _with_known_widgets_only used to discard the entire SemanticScene
  (returning None) when filtering dangling-element-id widgets left an
  empty list, losing valid page/intents. Now returns a SemanticScene
  with widgets=[] instead, matching design.md's 'dropped, not a hard
  failure' intent.
- Removed _SDK_UNAVAILABLE_EXCEPTION_NAMES, dead code left over from an
  abandoned name-based exception-matching approach; the blanket except
  Exception already maps every SDK failure correctly.

openspec: semantic-scene capability, archived change semantic-scene-runtime
2026-07-07 08:31:03 +08:00

61 lines
1.7 KiB
Python

from __future__ import annotations
import logging
from typing import Any, Protocol
from core.models import Scene
from semantic.config import SemanticConfig, load_config
from semantic.llm_client import AnthropicSemanticClient, EnrichmentUnavailable
from semantic.models import SemanticScene
logger = logging.getLogger(__name__)
class SemanticLLMClient(Protocol):
def enrich(self, scene_json: dict[str, Any], *, timeout: float) -> dict[str, Any]:
...
def enrich_scene(
scene: Scene,
*,
client: SemanticLLMClient | None = None,
config: SemanticConfig | None = None,
) -> SemanticScene | None:
settings = config or load_config()
if not settings.enabled:
return None
llm_client = client or AnthropicSemanticClient(model=settings.model)
try:
payload = llm_client.enrich(scene.to_dict(), timeout=settings.timeout)
semantic_scene = SemanticScene.from_dict(payload)
return _with_known_widgets_only(scene, semantic_scene)
except EnrichmentUnavailable as exc:
logger.info("semantic enrichment unavailable: %s", exc)
return None
except Exception as exc:
logger.info("semantic enrichment failed: %s", exc)
return None
def _with_known_widgets_only(
scene: Scene,
semantic_scene: SemanticScene,
) -> SemanticScene:
known_element_ids = {element.id for element in scene.elements}
if not known_element_ids:
return semantic_scene
widgets = [
widget
for widget in semantic_scene.widgets
if widget.element_id in known_element_ids
]
return SemanticScene(
page=semantic_scene.page,
intents=semantic_scene.intents,
widgets=widgets,
)