Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d5132e8
Add select to Imeon inverter integration (#150889)
Imeon-Energy Sep 11, 2025
1b99ffe
Pass satellite id through assist pipeline (#151992)
arturpragacz Sep 11, 2025
4762c64
Add initial support for Tuya msp category (cat toilet) (#152035)
epenet Sep 11, 2025
ab7081d
Include non-primary entities targeted directly by label (#149309)
abmantis Sep 11, 2025
bcfa7a7
squeezebox: Improve update notification string (#151003)
reedy Sep 11, 2025
254694b
Fix track icons for Apps and Radios in Squeezebox (#151001)
peteS-UK Sep 11, 2025
a368ad4
Set sensors to unknown when no next alarm is set in Sleep as Android …
tr4nt0r Sep 11, 2025
937d3e4
Add more light models to SwitchBot Cloud (#150986)
XiaoLing-git Sep 11, 2025
b1a6e40
Cache apt install [ci] (#152113)
cdce8p Sep 11, 2025
9cfdb99
Add repair to unsubscribe protected topic in ntfy integration (#152009)
tr4nt0r Sep 11, 2025
0e82956
Fail hassfest if translation key is obsolete (#151924)
joostlek Sep 11, 2025
596a3fc
Add async_current_scanners API to Bluetooth integration (#152122)
bdraco Sep 11, 2025
531b671
fix rain sensor for Velux GPU windows (#151857)
wollew Sep 11, 2025
442b6e9
Add initial support for Tuya sjz category (electric desk) (#152036)
epenet Sep 11, 2025
fea7f53
Bump thinqconnect to 1.0.8 (#152100)
LG-ThinQ-Integration Sep 11, 2025
4ad2916
Bump zcc-helper to 3.7 (#151807)
markhannon Sep 11, 2025
4f045b4
Fix supported _color_modes attribute not set for on/off MQTT JSON lig…
jbouwh Sep 11, 2025
c5d552d
Use translation_key in Tuya dr category (electric blanket) (#152099)
epenet Sep 11, 2025
0acd77e
Only use media path for TTS stream override (#152084)
synesthesiam Sep 11, 2025
5413131
Replace "cook time" with correct "cooking time" in `matter` (#152110)
NoRi2909 Sep 11, 2025
27c0df3
Add CPU temperature sensor to AVM FRITZ!Box Tools (#151328)
CooperRS Sep 11, 2025
66d1cf8
Add missing period in "H.264" standard name in `onvif` (#152132)
NoRi2909 Sep 11, 2025
ae70ca7
Add `sw_version` to Shelly BLU TRV device info (#152129)
bieniu Sep 11, 2025
4985f9a
Fix reauth for Alexa Devices (#152128)
chemelli74 Sep 11, 2025
b12c458
Log bayesian sensor name for unavailable observations (#152039)
HarvsG Sep 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 118 additions & 8 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ on:
type: boolean

env:
CACHE_VERSION: 7
CACHE_VERSION: 8
UV_CACHE_VERSION: 1
MYPY_CACHE_VERSION: 1
HA_SHORT_VERSION: "2025.10"
Expand All @@ -61,6 +61,9 @@ env:
POSTGRESQL_VERSIONS: "['postgres:12.14','postgres:15.2']"
PRE_COMMIT_CACHE: ~/.cache/pre-commit
UV_CACHE_DIR: /tmp/uv-cache
APT_CACHE_BASE: /home/runner/work/apt
APT_CACHE_DIR: /home/runner/work/apt/cache
APT_LIST_CACHE_DIR: /home/runner/work/apt/lists
SQLALCHEMY_WARN_20: 1
PYTHONASYNCIODEBUG: 1
HASS_CI: 1
Expand All @@ -78,6 +81,7 @@ jobs:
core: ${{ steps.core.outputs.changes }}
integrations_glob: ${{ steps.info.outputs.integrations_glob }}
integrations: ${{ steps.integrations.outputs.changes }}
apt_cache_key: ${{ steps.generate_apt_cache_key.outputs.key }}
pre-commit_cache_key: ${{ steps.generate_pre-commit_cache_key.outputs.key }}
python_cache_key: ${{ steps.generate_python_cache_key.outputs.key }}
requirements: ${{ steps.core.outputs.requirements }}
Expand Down Expand Up @@ -111,6 +115,10 @@ jobs:
run: >-
echo "key=pre-commit-${{ env.CACHE_VERSION }}-${{
hashFiles('.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT
- name: Generate partial apt restore key
id: generate_apt_cache_key
run: |
echo "key=$(lsb_release -rs)-apt-${{ env.CACHE_VERSION }}-${{ env.HA_SHORT_VERSION }}" >> $GITHUB_OUTPUT
- name: Filter for core changes
uses: dorny/paths-filter@v3.0.2
id: core
Expand Down Expand Up @@ -515,16 +523,36 @@ jobs:
${{ runner.os }}-${{ runner.arch }}-${{ steps.python.outputs.python-version }}-uv-${{
env.UV_CACHE_VERSION }}-${{ steps.generate-uv-key.outputs.version }}-${{
env.HA_SHORT_VERSION }}-
- name: Restore apt cache
if: steps.cache-venv.outputs.cache-hit != 'true'
id: cache-apt
uses: actions/cache@v4.2.4
with:
path: |
${{ env.APT_CACHE_DIR }}
${{ env.APT_LIST_CACHE_DIR }}
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }}
- name: Install additional OS dependencies
if: steps.cache-venv.outputs.cache-hit != 'true'
timeout-minutes: 10
run: |
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update
if [[ "${{ steps.cache-apt.outputs.cache-hit }}" != 'true' ]]; then
mkdir -p ${{ env.APT_CACHE_DIR }}
mkdir -p ${{ env.APT_LIST_CACHE_DIR }}
fi

sudo apt-get update \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }}
sudo apt-get -y install \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }} \
bluez \
ffmpeg \
libturbojpeg \
libxml2-utils \
libavcodec-dev \
libavdevice-dev \
libavfilter-dev \
Expand All @@ -534,6 +562,10 @@ jobs:
libswresample-dev \
libswscale-dev \
libudev-dev

if [[ "${{ steps.cache-apt.outputs.cache-hit }}" != 'true' ]]; then
sudo chmod -R 755 ${{ env.APT_CACHE_BASE }}
fi
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
Expand Down Expand Up @@ -578,12 +610,25 @@ jobs:
- info
- base
steps:
- name: Restore apt cache
uses: actions/cache/restore@v4.2.4
with:
path: |
${{ env.APT_CACHE_DIR }}
${{ env.APT_LIST_CACHE_DIR }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }}
- name: Install additional OS dependencies
timeout-minutes: 10
run: |
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update
sudo apt-get update \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }}
sudo apt-get -y install \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }} \
libturbojpeg
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
Expand Down Expand Up @@ -878,12 +923,25 @@ jobs:
- mypy
name: Split tests for full run
steps:
- name: Restore apt cache
uses: actions/cache/restore@v4.2.4
with:
path: |
${{ env.APT_CACHE_DIR }}
${{ env.APT_LIST_CACHE_DIR }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }}
- name: Install additional OS dependencies
timeout-minutes: 10
run: |
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update
sudo apt-get update \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }}
sudo apt-get -y install \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }} \
bluez \
ffmpeg \
libturbojpeg \
Expand Down Expand Up @@ -939,12 +997,25 @@ jobs:
name: >-
Run tests Python ${{ matrix.python-version }} (${{ matrix.group }})
steps:
- name: Restore apt cache
uses: actions/cache/restore@v4.2.4
with:
path: |
${{ env.APT_CACHE_DIR }}
${{ env.APT_LIST_CACHE_DIR }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }}
- name: Install additional OS dependencies
timeout-minutes: 10
run: |
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update
sudo apt-get update \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }}
sudo apt-get -y install \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }} \
bluez \
ffmpeg \
libturbojpeg \
Expand Down Expand Up @@ -1073,12 +1144,25 @@ jobs:
name: >-
Run ${{ matrix.mariadb-group }} tests Python ${{ matrix.python-version }}
steps:
- name: Restore apt cache
uses: actions/cache/restore@v4.2.4
with:
path: |
${{ env.APT_CACHE_DIR }}
${{ env.APT_LIST_CACHE_DIR }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }}
- name: Install additional OS dependencies
timeout-minutes: 10
run: |
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update
sudo apt-get update \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }}
sudo apt-get -y install \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }} \
bluez \
ffmpeg \
libturbojpeg \
Expand Down Expand Up @@ -1214,12 +1298,25 @@ jobs:
name: >-
Run ${{ matrix.postgresql-group }} tests Python ${{ matrix.python-version }}
steps:
- name: Restore apt cache
uses: actions/cache/restore@v4.2.4
with:
path: |
${{ env.APT_CACHE_DIR }}
${{ env.APT_LIST_CACHE_DIR }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }}
- name: Install additional OS dependencies
timeout-minutes: 10
run: |
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update
sudo apt-get update \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }}
sudo apt-get -y install \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }} \
bluez \
ffmpeg \
libturbojpeg \
Expand Down Expand Up @@ -1376,12 +1473,25 @@ jobs:
name: >-
Run tests Python ${{ matrix.python-version }} (${{ matrix.group }})
steps:
- name: Restore apt cache
uses: actions/cache/restore@v4.2.4
with:
path: |
${{ env.APT_CACHE_DIR }}
${{ env.APT_LIST_CACHE_DIR }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ runner.arch }}-${{ needs.info.outputs.apt_cache_key }}
- name: Install additional OS dependencies
timeout-minutes: 10
run: |
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update
sudo apt-get update \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }}
sudo apt-get -y install \
-o Dir::Cache=${{ env.APT_CACHE_DIR }} \
-o Dir::State::Lists=${{ env.APT_LIST_CACHE_DIR }} \
bluez \
ffmpeg \
libturbojpeg \
Expand Down
7 changes: 5 additions & 2 deletions homeassistant/components/alexa_devices/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ async def async_step_reauth_confirm(

if user_input is not None:
try:
await validate_input(self.hass, {**reauth_entry.data, **user_input})
data = await validate_input(
self.hass, {**reauth_entry.data, **user_input}
)
except CannotConnect:
errors["base"] = "cannot_connect"
except (CannotAuthenticate, TypeError):
Expand All @@ -119,8 +121,9 @@ async def async_step_reauth_confirm(
reauth_entry,
data={
CONF_USERNAME: entry_data[CONF_USERNAME],
CONF_PASSWORD: entry_data[CONF_PASSWORD],
CONF_PASSWORD: user_input[CONF_PASSWORD],
CONF_CODE: user_input[CONF_CODE],
CONF_LOGIN_DATA: data,
},
)

Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/assist_pipeline/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ async def async_pipeline_from_audio_stream(
wake_word_settings: WakeWordSettings | None = None,
audio_settings: AudioSettings | None = None,
device_id: str | None = None,
satellite_id: str | None = None,
start_stage: PipelineStage = PipelineStage.STT,
end_stage: PipelineStage = PipelineStage.TTS,
conversation_extra_system_prompt: str | None = None,
Expand All @@ -115,6 +116,7 @@ async def async_pipeline_from_audio_stream(
pipeline_input = PipelineInput(
session=session,
device_id=device_id,
satellite_id=satellite_id,
stt_metadata=stt_metadata,
stt_stream=stt_stream,
wake_word_phrase=wake_word_phrase,
Expand Down
26 changes: 20 additions & 6 deletions homeassistant/components/assist_pipeline/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,9 @@ class PipelineRun:
_device_id: str | None = None
"""Optional device id set during run start."""

_satellite_id: str | None = None
"""Optional satellite id set during run start."""

_conversation_data: PipelineConversationData | None = None
"""Data tied to the conversation ID."""

Expand Down Expand Up @@ -636,16 +639,21 @@ def process_event(self, event: PipelineEvent) -> None:
return
pipeline_data.pipeline_debug[self.pipeline.id][self.id].events.append(event)

def start(self, conversation_id: str, device_id: str | None) -> None:
def start(
self, conversation_id: str, device_id: str | None, satellite_id: str | None
) -> None:
"""Emit run start event."""
self._device_id = device_id
self._satellite_id = satellite_id
self._start_debug_recording_thread()

data: dict[str, Any] = {
"pipeline": self.pipeline.id,
"language": self.language,
"conversation_id": conversation_id,
}
if satellite_id is not None:
data["satellite_id"] = satellite_id
if self.runner_data is not None:
data["runner_data"] = self.runner_data
if self.tts_stream:
Expand Down Expand Up @@ -1057,7 +1065,6 @@ async def recognize_intent(
self,
intent_input: str,
conversation_id: str,
device_id: str | None,
conversation_extra_system_prompt: str | None,
) -> str:
"""Run intent recognition portion of pipeline. Returns text to speak."""
Expand Down Expand Up @@ -1088,7 +1095,8 @@ async def recognize_intent(
"language": input_language,
"intent_input": intent_input,
"conversation_id": conversation_id,
"device_id": device_id,
"device_id": self._device_id,
"satellite_id": self._satellite_id,
"prefer_local_intents": self.pipeline.prefer_local_intents,
},
)
Expand All @@ -1099,7 +1107,8 @@ async def recognize_intent(
text=intent_input,
context=self.context,
conversation_id=conversation_id,
device_id=device_id,
device_id=self._device_id,
satellite_id=self._satellite_id,
language=input_language,
agent_id=self.intent_agent.id,
extra_system_prompt=conversation_extra_system_prompt,
Expand Down Expand Up @@ -1269,6 +1278,7 @@ async def tts_input_stream_generator() -> AsyncGenerator[str]:
text=user_input.text,
conversation_id=user_input.conversation_id,
device_id=user_input.device_id,
satellite_id=user_input.satellite_id,
context=user_input.context,
language=user_input.language,
agent_id=user_input.agent_id,
Expand Down Expand Up @@ -1567,10 +1577,15 @@ class PipelineInput:
device_id: str | None = None
"""Identifier of the device that is processing the input/output of the pipeline."""

satellite_id: str | None = None
"""Identifier of the satellite that is processing the input/output of the pipeline."""

async def execute(self) -> None:
"""Run pipeline."""
self.run.start(
conversation_id=self.session.conversation_id, device_id=self.device_id
conversation_id=self.session.conversation_id,
device_id=self.device_id,
satellite_id=self.satellite_id,
)
current_stage: PipelineStage | None = self.run.start_stage
stt_audio_buffer: list[EnhancedAudioChunk] = []
Expand Down Expand Up @@ -1656,7 +1671,6 @@ async def buffer_then_audio_stream() -> AsyncGenerator[
tts_input = await self.run.recognize_intent(
intent_input,
self.session.conversation_id,
self.device_id,
self.conversation_extra_system_prompt,
)
if tts_input.strip():
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/assist_satellite/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ async def async_accept_pipeline_from_satellite(
pipeline_id=self._resolve_pipeline(),
conversation_id=session.conversation_id,
device_id=device_id,
satellite_id=self.entity_id,
tts_audio_output=self.tts_options,
wake_word_phrase=wake_word_phrase,
audio_settings=AudioSettings(
Expand Down
Loading
Loading