Repository: home-assistant/core
File: homeassistant/components/intent/timers.py (Python)

Code before:
        self, intent_obj: intent.Intent, conversation_command: str
    ) -> bool:
        """Validate that a conversation command can be executed."""
        from homeassistant.components.conversation import (  # noqa: PLC0415
            ConversationEntity,
            ConversationEntityFeature,
            ConversationInput,
            async_get_agent,
            async_handle_intents,
        )

        # Skip validation for LLM agents with control
        conversation_agent = async_get_agent(
            intent_obj.hass, intent_obj.conversation_agent_id
        )

        if isinstance(conversation_agent, ConversationEntity):
            agent_state = intent_obj.hass.states.get(conversation_agent.entity_id)
            if (
                agent_state
                and ConversationEntityFeature.CONTROL
                and (
                    agent_state.attributes.get("supported_features", 0)
                    & ConversationEntityFeature.CONTROL
                )
            ):
                return True  # Skip validation

        test_input = ConversationInput(
            text=conversation_command,
            language=intent_obj.language,
            device_id=intent_obj.device_id,
            conversation_id=None,
            context=intent_obj.context,
            agent_id=str(intent_obj.conversation_agent_id),
        )

        recognize_result = await async_handle_intents(intent_obj.hass, test_input)
        if recognize_result is None:
            return False

        return True

    async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
        """Handle the intent."""
        hass = intent_obj.hass
        timer_manager: TimerManager = hass.data[TIMER_DATA]
        slots = self.async_validate_slots(intent_obj.slots)

        conversation_command: str | None = None
        if "conversation_command" in slots:

Review comment (suggestion):
Is there any reason we're not simply doing this?
```suggestion
            if ConversationEntityFeature.CONTROL in conversation_agent.supported_features:
```

Code after:
class StartTimerIntentHandler(intent.IntentHandler):
    """Intent handler for starting a new timer."""

    intent_type = intent.INTENT_START_TIMER
    description = "Starts a new timer"
    slot_schema = {
        vol.Required(vol.Any("hours", "minutes", "seconds")): cv.positive_int,
        vol.Optional("name"): cv.string,
        vol.Optional("conversation_command"): cv.string,
    }

    async def async_handle(self, intent_obj: intent.Intent) -> intent.IntentResponse:
        """Handle the intent."""
        hass = intent_obj.hass
        timer_manager: TimerManager = hass.data[TIMER_DATA]
        slots = self.async_validate_slots(intent_obj.slots)

        conversation_command: str | None = None
        if "conversation_command" in slots:
            conversation_command = slots["conversation_command"]["value"].strip()

        if (not conversation_command) and (
            not (
                intent_obj.device_id
                and timer_manager.is_timer_device(intent_obj.device_id)
            )
        ):
            # Fail early if this is not a delayed command
            raise TimersNotSupportedError(intent_obj.device_id)

        # Validate conversation command if provided
        if conversation_command and not await self._validate_conversation_command(
            intent_obj, conversation_command
        ):
            raise NoTimerCommandError(conversation_command)

        name: str | None = None
        if "name" in slots:
            name = slots["name"]["value"]

        hours: int | None = None
        if "hours" in slots:
            hours = int(slots["hours"]["value"])

        minutes: int | None = None
        if "minutes" in slots:
            minutes = int(slots["minutes"]["value"])

        seconds: int | None = None
        if "seconds" in slots:
            seconds = int(slots["seconds"]["value"])