diff --git a/build-scripts/webpack.cjs b/build-scripts/webpack.cjs index 7a6e943a72..fc0ce85cb6 100644 --- a/build-scripts/webpack.cjs +++ b/build-scripts/webpack.cjs @@ -152,14 +152,17 @@ const createWebpackConfig = ({ }, }, output: { - filename: ({ chunk }) => { - if (!isProdBuild || isStatsBuild || dontHash.has(chunk.name)) { - return `${chunk.name}.js`; - } - return `${chunk.name}.${chunk.hash.substr(0, 8)}.js`; - }, + filename: ({ chunk }) => + !isProdBuild || isStatsBuild || dontHash.has(chunk.name) + ? "[name].js" + : "[name]-[contenthash].js", chunkFilename: - isProdBuild && !isStatsBuild ? "[chunkhash:8].js" : "[id].chunk.js", + isProdBuild && !isStatsBuild ? "[id]-[contenthash].js" : "[name].js", + assetModuleFilename: + isProdBuild && !isStatsBuild ? "[id]-[contenthash][ext]" : "[id][ext]", + hashFunction: "xxhash64", + hashDigest: "base64url", + hashDigestLength: 11, // full length of 64 bit base64url path: outputPath, publicPath, // To silence warning in worker plugin diff --git a/package.json b/package.json index c72077d252..99ad81844b 100644 --- a/package.json +++ b/package.json @@ -186,13 +186,13 @@ "@types/webspeechapi": "0.0.29", "@typescript-eslint/eslint-plugin": "5.57.0", "@typescript-eslint/parser": "5.57.0", - "@web/dev-server": "0.1.36", + "@web/dev-server": "0.1.37", "@web/dev-server-rollup": "0.4.0", "babel-loader": "9.1.2", "babel-plugin-template-html-minifier": "4.1.0", "chai": "4.3.7", "del": "7.0.0", - "eslint": "8.36.0", + "eslint": "8.37.0", "eslint-config-airbnb-base": "15.0.0", "eslint-config-airbnb-typescript": "17.0.0", "eslint-config-prettier": "8.8.0", diff --git a/pyproject.toml b/pyproject.toml index d550f7471a..7396a23278 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20230331.0" +version = "20230401.0" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" diff --git a/src/data/selector.ts b/src/data/selector.ts index 12168d435e..91119bc2ec 100644 --- a/src/data/selector.ts +++ b/src/data/selector.ts @@ -1,5 +1,7 @@ import type { HassEntity } from "home-assistant-js-websocket"; +import { ensureArray } from "../common/array/ensure-array"; import { computeStateDomain } from "../common/entity/compute_state_domain"; +import { supportsFeature } from "../common/entity/supports-feature"; import { UiAction } from "../panels/lovelace/components/hui-action-editor"; import type { DeviceRegistryEntry } from "./device_registry"; import type { EntitySources } from "./entity_sources"; @@ -149,6 +151,7 @@ interface EntitySelectorFilter { integration?: string; domain?: string | readonly string[]; device_class?: string | readonly string[]; + supported_features?: number | [number]; } export interface EntitySelector { @@ -358,6 +361,7 @@ export const filterSelectorEntities = ( const { domain: filterDomain, device_class: filterDeviceClass, + supported_features: filterSupportedFeature, integration: filterIntegration, } = filterEntity; @@ -383,6 +387,16 @@ export const filterSelectorEntities = ( } } + if (filterSupportedFeature) { + if ( + ensureArray(filterSupportedFeature).some( + (feature) => !supportsFeature(entity, feature) + ) + ) { + return false; + } + } + if ( filterIntegration && entitySources?.[entity.entity_id]?.domain !== filterIntegration diff --git a/src/data/voice_assistant.ts b/src/data/voice_assistant.ts index 0de01e1db0..c332e19267 100644 --- a/src/data/voice_assistant.ts +++ b/src/data/voice_assistant.ts @@ -14,6 +14,7 @@ interface PipelineRunStartEvent extends PipelineEventBase { language: string; runner_data: { stt_binary_handler_id: number | null; + timeout: number; }; }; } @@ -40,7 +41,7 @@ interface PipelineSTTStartEvent extends PipelineEventBase { interface PipelineSTTEndEvent extends PipelineEventBase { type: "stt-end"; data: { - text: string; + stt_output: { text: string }; }; } diff --git a/src/layouts/home-assistant-main.ts b/src/layouts/home-assistant-main.ts index 32e9503956..c0a116163a 100644 --- a/src/layouts/home-assistant-main.ts +++ b/src/layouts/home-assistant-main.ts @@ -7,11 +7,11 @@ import { PropertyValues, TemplateResult, } from "lit"; -import "@material/mwc-drawer/mwc-drawer"; import { customElement, property, state } from "lit/decorators"; import { fireEvent, HASSDomEvent } from "../common/dom/fire_event"; import { listenMediaQuery } from "../common/dom/media_query"; import { toggleAttribute } from "../common/dom/toggle_attribute"; +import "../components/ha-drawer"; import { showNotificationDrawer } from "../dialogs/notifications/show-notification-drawer"; import type { HomeAssistant, Route } from "../types"; import "./partial-panel-resolver"; @@ -58,7 +58,7 @@ export class HomeAssistantMain extends LitElement { const sidebarNarrow = this._sidebarNarrow || this._externalSidebar; return html` - - + `; } diff --git a/src/panels/config/integrations/integration-panels/voice_assistant/assist/assist-pipeline-debug.ts b/src/panels/config/integrations/integration-panels/voice_assistant/assist/assist-pipeline-debug.ts index 7e95f9b590..c0dcd3d5af 100644 --- a/src/panels/config/integrations/integration-panels/voice_assistant/assist/assist-pipeline-debug.ts +++ b/src/panels/config/integrations/integration-panels/voice_assistant/assist/assist-pipeline-debug.ts @@ -1,317 +1,131 @@ import { css, html, LitElement, PropertyValues, TemplateResult } from "lit"; -import { customElement, property, state } from "lit/decorators"; -import "../../../../../../components/ha-card"; -import "../../../../../../components/ha-alert"; +import { customElement, property, query, state } from "lit/decorators"; import "../../../../../../components/ha-button"; -import "../../../../../../components/ha-circular-progress"; -import "../../../../../../components/ha-expansion-panel"; -import "../../../../../../components/ha-textfield"; import { PipelineRun, runPipelineFromText, } from "../../../../../../data/voice_assistant"; import "../../../../../../layouts/hass-subpage"; -import { SubscribeMixin } from "../../../../../../mixins/subscribe-mixin"; +import "../../../../../../components/ha-formfield"; +import "../../../../../../components/ha-checkbox"; import { haStyle } from "../../../../../../resources/styles"; import type { HomeAssistant } from "../../../../../../types"; -import { formatNumber } from "../../../../../../common/number/format_number"; import { showPromptDialog } from "../../../../../../dialogs/generic/show-dialog-box"; - -const RUN_DATA = { - pipeline: "Pipeline", - language: "Language", -}; - -const STT_DATA = { - engine: "Engine", -}; - -const INTENT_DATA = { - engine: "Engine", - intent_input: "Input", -}; - -const TTS_DATA = { - engine: "Engine", - tts_input: "Input", -}; - -const STAGES: Record = { - ready: 0, - stt: 1, - intent: 2, - tts: 3, - done: 4, - error: 5, -}; - -const hasStage = (run: PipelineRun, stage: PipelineRun["stage"]) => - STAGES[run.init_options.start_stage] <= STAGES[stage] && - STAGES[stage] <= STAGES[run.init_options.end_stage]; - -const maybeRenderError = ( - run: PipelineRun, - stage: string, - lastRunStage: string -) => { - if (run.stage !== "error" || lastRunStage !== stage) { - return ""; - } - - return html` - ${run.error!.message} (${run.error!.code}) - `; -}; - -const renderProgress = ( - hass: HomeAssistant, - pipelineRun: PipelineRun, - stage: PipelineRun["stage"] -) => { - const startEvent = pipelineRun.events.find( - (ev) => ev.type === `${stage}-start` - ); - const finishEvent = pipelineRun.events.find( - (ev) => ev.type === `${stage}-end` - ); - - if (!startEvent) { - return ""; - } - - if (pipelineRun.stage === "error") { - return html`❌`; - } - - if (!finishEvent) { - return html``; - } - - const duration = - new Date(finishEvent.timestamp).getTime() - - new Date(startEvent.timestamp).getTime(); - const durationString = formatNumber(duration / 1000, hass.locale, { - maximumFractionDigits: 2, - }); - return html`${durationString}s ✅`; -}; - -const renderData = (data: Record, keys: Record) => - Object.entries(keys).map( - ([key, label]) => - html` -
-
${label}
-
${data[key]}
-
- ` - ); - -const dataMinusKeysRender = ( - data: Record, - keys: Record -) => { - const result = {}; - let render = false; - for (const key in data) { - if (key in keys) { - continue; - } - render = true; - result[key] = data[key]; - } - return render ? html`
${JSON.stringify(result, null, 2)}
` : ""; -}; +import "./assist-render-pipeline-run"; +import type { HaCheckbox } from "../../../../../../components/ha-checkbox"; +import type { HaTextField } from "../../../../../../components/ha-textfield"; +import "../../../../../../components/ha-textfield"; @customElement("assist-pipeline-debug") -export class AssistPipelineDebug extends SubscribeMixin(LitElement) { +export class AssistPipelineDebug extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property({ type: Boolean }) public narrow!: boolean; - @state() private _pipelineRun?: PipelineRun; + @state() private _pipelineRuns: PipelineRun[] = []; @state() private _stopRecording?: () => void; + @query("#continue-conversation") + private _continueConversationCheckbox!: HaCheckbox; + + @query("#continue-conversation-text") + private _continueConversationTextField?: HaTextField; + private _audioBuffer?: Int16Array[]; - protected render(): TemplateResult { - const lastRunStage: string = this._pipelineRun - ? ["tts", "intent", "stt"].find( - (stage) => this._pipelineRun![stage] !== undefined - ) || "ready" - : "ready"; + @state() private _finished = false; + protected render(): TemplateResult { return html` + ${this._pipelineRuns.length > 0 + ? html` + + Clear + + ` + : ""} +
- - Run Text Pipeline - - - Run Audio Pipeline - + ${this._pipelineRuns.length === 0 + ? html` + + Run Text Pipeline + + + Run Audio Pipeline + + ` + : this._pipelineRuns[0].init_options.start_stage === "intent" + ? html` + + + Send + + ` + : html` + + + + `}
- ${this._pipelineRun - ? html` - -
-
-
Run
-
${this._pipelineRun.stage}
-
- - ${renderData(this._pipelineRun.run, RUN_DATA)} -
-
- - ${maybeRenderError(this._pipelineRun, "ready", lastRunStage)} - ${hasStage(this._pipelineRun, "stt") - ? html` - -
-
- Speech-to-Text - ${renderProgress( - this.hass, - this._pipelineRun, - "stt" - )} -
- ${this._pipelineRun.stt - ? html` -
- ${renderData(this._pipelineRun.stt, STT_DATA)} - ${dataMinusKeysRender( - this._pipelineRun.stt, - STT_DATA - )} -
- ` - : ""} -
- ${this._pipelineRun.stage === "stt" && - this._stopRecording - ? html` -
- - Stop Recording - -
- ` - : ""} -
- ` - : ""} - ${maybeRenderError(this._pipelineRun, "stt", lastRunStage)} - ${hasStage(this._pipelineRun, "intent") - ? html` - -
-
- Natural Language Processing - ${renderProgress( - this.hass, - this._pipelineRun, - "intent" - )} -
- ${this._pipelineRun.intent - ? html` -
- ${renderData( - this._pipelineRun.intent, - INTENT_DATA - )} - ${dataMinusKeysRender( - this._pipelineRun.intent, - INTENT_DATA - )} -
- ` - : ""} -
-
- ` - : ""} - ${maybeRenderError(this._pipelineRun, "intent", lastRunStage)} - ${hasStage(this._pipelineRun, "tts") - ? html` - -
-
- Text-to-Speech - ${renderProgress( - this.hass, - this._pipelineRun, - "tts" - )} -
- ${this._pipelineRun.tts - ? html` -
- ${renderData(this._pipelineRun.tts, TTS_DATA)} -
- ` - : ""} -
- ${this._pipelineRun?.tts?.tts_output - ? html` -
- - Play Audio - -
- ` - : ""} -
- ` - : ""} - ${maybeRenderError(this._pipelineRun, "tts", lastRunStage)} - - - Raw -
${JSON.stringify(this._pipelineRun, null, 2)}
-
-
- ` - : ""} + ${this._pipelineRuns.map((run) => + run === null + ? "" + : html` + + ` + )}
`; } - protected updated(changedProperties: PropertyValues): void { - super.updated(changedProperties); + protected willUpdate(changedProperties: PropertyValues): void { + super.willUpdate(changedProperties); if ( - !changedProperties.has("_pipelineRun") || - !this._pipelineRun || - this._pipelineRun.init_options.start_stage !== "stt" + !changedProperties.has("_pipelineRuns") || + this._pipelineRuns.length === 0 ) { return; } - if (this._pipelineRun.stage === "stt" && this._audioBuffer) { + const currentRun = this._pipelineRuns[0]; + + if (currentRun.init_options.start_stage !== "stt") { + if (["error", "done"].includes(currentRun.stage)) { + this._finished = true; + } + return; + } + + if (currentRun.stage === "stt" && this._audioBuffer) { // Send the buffer over the WS to the STT engine. for (const buffer of this._audioBuffer) { this._sendAudioChunk(buffer); @@ -319,31 +133,70 @@ export class AssistPipelineDebug extends SubscribeMixin(LitElement) { this._audioBuffer = undefined; } - if (this._pipelineRun.stage !== "stt" && this._stopRecording) { + if (currentRun.stage !== "stt" && this._stopRecording) { this._stopRecording(); } + + if (currentRun.stage === "done") { + const url = currentRun.tts!.tts_output!.url; + const audio = new Audio(url); + audio.addEventListener("ended", () => { + if (this._continueConversationCheckbox.checked) { + this._runAudioPipeline(); + } else { + this._finished = true; + } + }); + audio.play(); + } else if (currentRun.stage === "error") { + this._finished = true; + } + } + + private get conversationId(): string | null { + return this._pipelineRuns.length === 0 + ? null + : this._pipelineRuns[0].intent?.intent_output?.conversation_id || null; } private async _runTextPipeline() { - const text = await showPromptDialog(this, { - title: "Input text", - confirmText: "Run", - }); + const textfield = this._continueConversationTextField; + + let text: string | null; + + if (textfield) { + text = textfield.value; + } else { + text = await showPromptDialog(this, { + title: "Input text", + confirmText: "Run", + }); + } if (!text) { return; } - this._pipelineRun = undefined; + let added = false; runPipelineFromText( this.hass, (run) => { - this._pipelineRun = run; + if (textfield && ["done", "error"].includes(run.stage)) { + textfield.value = ""; + } + + if (added) { + this._pipelineRuns = [run, ...this._pipelineRuns.slice(1)]; + } else { + this._pipelineRuns = [run, ...this._pipelineRuns]; + added = true; + } }, { start_stage: "intent", end_stage: "intent", input: { text }, + conversation_id: this.conversationId, } ); } @@ -375,21 +228,28 @@ export class AssistPipelineDebug extends SubscribeMixin(LitElement) { this._audioBuffer.push(e.data); return; } - if (this._pipelineRun?.stage !== "stt") { + if (this._pipelineRuns[0].stage !== "stt") { return; } this._sendAudioChunk(e.data); }; - this._pipelineRun = undefined; + this._finished = false; + let added = false; runPipelineFromText( this.hass, (run) => { - this._pipelineRun = run; + if (added) { + this._pipelineRuns = [run, ...this._pipelineRuns.slice(1)]; + } else { + this._pipelineRuns = [run, ...this._pipelineRuns]; + added = true; + } }, { start_stage: "stt", end_stage: "tts", + conversation_id: this.conversationId, } ); } @@ -397,16 +257,20 @@ export class AssistPipelineDebug extends SubscribeMixin(LitElement) { private _sendAudioChunk(chunk: Int16Array) { // Turn into 8 bit so we can prefix our handler ID. const data = new Uint8Array(1 + chunk.length * 2); - data[0] = this._pipelineRun!.run.runner_data.stt_binary_handler_id!; + data[0] = this._pipelineRuns[0].run.runner_data.stt_binary_handler_id!; data.set(new Uint8Array(chunk.buffer), 1); this.hass.connection.socket!.send(data); } - private _playTTS(): void { - const url = this._pipelineRun!.tts!.tts_output!.url; - const audio = new Audio(url); - audio.play(); + private _handleContinueKeyDown(ev) { + if (ev.keyCode === 13) { + this._runTextPipeline(); + } + } + + private _clearConversation() { + this._pipelineRuns = []; } static styles = [ @@ -419,32 +283,19 @@ export class AssistPipelineDebug extends SubscribeMixin(LitElement) { direction: ltr; } .start-row { - text-align: center; - } - .start-row ha-button { - margin: 16px; - } - ha-card, - ha-alert { - display: block; - margin-bottom: 16px; - } - .run-pipeline-card ha-textfield { - display: block; - } - .row { display: flex; - justify-content: space-between; + justify-content: space-around; + align-items: center; + margin: 0 16px 16px; } - pre { - margin: 0; + .start-row ha-textfield { + flex: 1; } - ha-expansion-panel { - padding-left: 8px; + assist-render-pipeline-run { + padding-top: 16px; } - .heading { - font-weight: 500; - margin-bottom: 16px; + assist-render-pipeline-run + assist-render-pipeline-run { + border-top: 3px solid black; } `, ]; diff --git a/src/panels/config/integrations/integration-panels/voice_assistant/assist/assist-render-pipeline-run.ts b/src/panels/config/integrations/integration-panels/voice_assistant/assist/assist-render-pipeline-run.ts new file mode 100644 index 0000000000..f9940e0cb2 --- /dev/null +++ b/src/panels/config/integrations/integration-panels/voice_assistant/assist/assist-render-pipeline-run.ts @@ -0,0 +1,336 @@ +import { css, html, LitElement, TemplateResult } from "lit"; +import { customElement, property } from "lit/decorators"; +import "../../../../../../components/ha-card"; +import "../../../../../../components/ha-alert"; +import "../../../../../../components/ha-button"; +import "../../../../../../components/ha-circular-progress"; +import "../../../../../../components/ha-expansion-panel"; +import type { PipelineRun } from "../../../../../../data/voice_assistant"; +import type { HomeAssistant } from "../../../../../../types"; +import { formatNumber } from "../../../../../../common/number/format_number"; + +const RUN_DATA = { + pipeline: "Pipeline", + language: "Language", +}; + +const STT_DATA = { + engine: "Engine", +}; + +const INTENT_DATA = { + engine: "Engine", + intent_input: "Input", +}; + +const TTS_DATA = { + engine: "Engine", + tts_input: "Input", +}; + +const STAGES: Record = { + ready: 0, + stt: 1, + intent: 2, + tts: 3, + done: 4, + error: 5, +}; + +const hasStage = (run: PipelineRun, stage: PipelineRun["stage"]) => + STAGES[run.init_options.start_stage] <= STAGES[stage] && + STAGES[stage] <= STAGES[run.init_options.end_stage]; + +const maybeRenderError = ( + run: PipelineRun, + stage: string, + lastRunStage: string +) => { + if (run.stage !== "error" || lastRunStage !== stage) { + return ""; + } + + return html` + ${run.error!.message} (${run.error!.code}) + `; +}; + +const renderProgress = ( + hass: HomeAssistant, + pipelineRun: PipelineRun, + stage: PipelineRun["stage"] +) => { + const startEvent = pipelineRun.events.find( + (ev) => ev.type === `${stage}-start` + ); + const finishEvent = pipelineRun.events.find( + (ev) => ev.type === `${stage}-end` + ); + + if (!startEvent) { + return ""; + } + + if (pipelineRun.stage === "error") { + return html`❌`; + } + + if (!finishEvent) { + return html``; + } + + const duration = + new Date(finishEvent.timestamp).getTime() - + new Date(startEvent.timestamp).getTime(); + const durationString = formatNumber(duration / 1000, hass.locale, { + maximumFractionDigits: 2, + }); + return html`${durationString}s ✅`; +}; + +const renderData = (data: Record, keys: Record) => + Object.entries(keys).map( + ([key, label]) => + html` +
+
${label}
+
${data[key]}
+
+ ` + ); + +const dataMinusKeysRender = ( + data: Record, + keys: Record +) => { + const result = {}; + let render = false; + for (const key in data) { + if (key in keys) { + continue; + } + render = true; + result[key] = data[key]; + } + return render ? html`
${JSON.stringify(result, null, 2)}
` : ""; +}; + +@customElement("assist-render-pipeline-run") +export class AssistPipelineDebug extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property() private pipelineRun!: PipelineRun; + + protected render(): TemplateResult { + const lastRunStage: string = this.pipelineRun + ? ["tts", "intent", "stt"].find( + (stage) => this.pipelineRun![stage] !== undefined + ) || "ready" + : "ready"; + + const messages: Array<{ from: string; text: string }> = []; + + const userMessage = + this.pipelineRun.init_options.input?.text || + this.pipelineRun?.stt?.stt_output?.text; + + if (userMessage) { + messages.push({ + from: "user", + text: userMessage, + }); + } + + if ( + this.pipelineRun?.intent?.intent_output?.response?.speech?.plain?.speech + ) { + messages.push({ + from: "hass", + text: this.pipelineRun.intent.intent_output.response.speech.plain + .speech, + }); + } + + return html` + +
+
+
Run
+
${this.pipelineRun.stage}
+
+ + ${renderData(this.pipelineRun.run, RUN_DATA)} + ${messages.length > 0 + ? html` +
+ ${messages.map( + ({ from, text }) => html` +
${text}
+ ` + )} +
+
+ ` + : ""} +
+
+ + ${maybeRenderError(this.pipelineRun, "ready", lastRunStage)} + ${hasStage(this.pipelineRun, "stt") + ? html` + +
+
+ Speech-to-Text + ${renderProgress(this.hass, this.pipelineRun, "stt")} +
+ ${this.pipelineRun.stt + ? html` +
+ ${renderData(this.pipelineRun.stt, STT_DATA)} + ${dataMinusKeysRender(this.pipelineRun.stt, STT_DATA)} +
+ ` + : ""} +
+
+ ` + : ""} + ${maybeRenderError(this.pipelineRun, "stt", lastRunStage)} + ${hasStage(this.pipelineRun, "intent") + ? html` + +
+
+ Natural Language Processing + ${renderProgress(this.hass, this.pipelineRun, "intent")} +
+ ${this.pipelineRun.intent + ? html` +
+ ${renderData(this.pipelineRun.intent, INTENT_DATA)} + ${dataMinusKeysRender( + this.pipelineRun.intent, + INTENT_DATA + )} +
+ ` + : ""} +
+
+ ` + : ""} + ${maybeRenderError(this.pipelineRun, "intent", lastRunStage)} + ${hasStage(this.pipelineRun, "tts") + ? html` + +
+
+ Text-to-Speech + ${renderProgress(this.hass, this.pipelineRun, "tts")} +
+ ${this.pipelineRun.tts + ? html` +
+ ${renderData(this.pipelineRun.tts, TTS_DATA)} +
+ ` + : ""} +
+ ${this.pipelineRun?.tts?.tts_output + ? html` +
+ + Play Audio + +
+ ` + : ""} +
+ ` + : ""} + ${maybeRenderError(this.pipelineRun, "tts", lastRunStage)} + + + Raw +
${JSON.stringify(this.pipelineRun, null, 2)}
+
+
+ `; + } + + private _playTTS(): void { + const url = this.pipelineRun!.tts!.tts_output!.url; + const audio = new Audio(url); + audio.play(); + } + + static styles = css` + :host { + display: block; + } + ha-card, + ha-alert { + display: block; + margin-bottom: 16px; + } + .row { + display: flex; + justify-content: space-between; + } + pre { + margin: 0; + } + ha-expansion-panel { + padding-left: 8px; + } + .heading { + font-weight: 500; + margin-bottom: 16px; + } + + .messages { + margin-top: 8px; + } + + .message { + font-size: 18px; + margin: 8px 0; + padding: 8px; + border-radius: 15px; + clear: both; + } + + .message.user { + margin-left: 24px; + margin-inline-start: 24px; + margin-inline-end: initial; + float: var(--float-end); + text-align: right; + border-bottom-right-radius: 0px; + background-color: var(--light-primary-color); + color: var(--text-light-primary-color, var(--primary-text-color)); + direction: var(--direction); + } + + .message.hass { + margin-right: 24px; + margin-inline-end: 24px; + margin-inline-start: initial; + float: var(--float-start); + border-bottom-left-radius: 0px; + background-color: var(--primary-color); + color: var(--text-primary-color); + direction: var(--direction); + } + `; +} + +declare global { + interface HTMLElementTagNameMap { + "assist-render-pipeline-run": AssistPipelineDebug; + } +} diff --git a/yarn.lock b/yarn.lock index 7441d01ce8..cab79d905a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1484,27 +1484,27 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.0.1": - version: 2.0.1 - resolution: "@eslint/eslintrc@npm:2.0.1" +"@eslint/eslintrc@npm:^2.0.2": + version: 2.0.2 + resolution: "@eslint/eslintrc@npm:2.0.2" dependencies: ajv: ^6.12.4 debug: ^4.3.2 - espree: ^9.5.0 + espree: ^9.5.1 globals: ^13.19.0 ignore: ^5.2.0 import-fresh: ^3.2.1 js-yaml: ^4.1.0 minimatch: ^3.1.2 strip-json-comments: ^3.1.1 - checksum: 56b9192a687a450db53a7b883daf9f0f447c43b3510189cf88808a7a2467c2a302a42a50f184cc6d5a9faf3d1df890a2ef0fd0d60b751f32a3e9dfea717c6b48 + checksum: cfcf5e12c7b2c4476482e7f12434e76eae16fcd163ee627309adb10b761e5caa4a4e52ed7be464423320ff3d11eca5b50de5bf8be3e25834222470835dd5c801 languageName: node linkType: hard -"@eslint/js@npm:8.36.0": - version: 8.36.0 - resolution: "@eslint/js@npm:8.36.0" - checksum: b7d6b84b823c8c7784be390741196617565527b1f7c0977fde9455bfb57fd88f81c074a03dd878757d2c33fa29f24291e9ecbc1425710f067917324b55e1bf3a +"@eslint/js@npm:8.37.0": + version: 8.37.0 + resolution: "@eslint/js@npm:8.37.0" + checksum: 7a07fb085c94ce1538949012c292fd3a6cd734f149bc03af6157dfbd8a7477678899ef57b4a27e15b36470a997389ad79a0533d5880c71e67720ae1a7de7c62d languageName: node linkType: hard @@ -4968,9 +4968,9 @@ __metadata: languageName: node linkType: hard -"@web/dev-server@npm:0.1.36": - version: 0.1.36 - resolution: "@web/dev-server@npm:0.1.36" +"@web/dev-server@npm:0.1.37": + version: 0.1.37 + resolution: "@web/dev-server@npm:0.1.37" dependencies: "@babel/code-frame": ^7.12.11 "@types/command-line-args": ^5.0.0 @@ -4989,7 +4989,7 @@ __metadata: bin: wds: dist/bin.js web-dev-server: dist/bin.js - checksum: 4bbf3334380ebceb7dac12f985681194c8ea7eb5ab48e35a65b54602c4a2be5087b41c03daa28b9912257b988759ac5fedf79a23a7dbbaf794bbf914a3b82876 + checksum: ca76c67dbeb8335ef4ace750ae1e1a50e49e53cc8a1edcb8c12ba05bc26ac44771e7b30b4d303061a51c9dbcdeb3861805c9ee1267d1880c6a672c2adec40270 languageName: node linkType: hard @@ -7954,21 +7954,21 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.3.0": - version: 3.3.0 - resolution: "eslint-visitor-keys@npm:3.3.0" - checksum: d59e68a7c5a6d0146526b0eec16ce87fbf97fe46b8281e0d41384224375c4e52f5ffb9e16d48f4ea50785cde93f766b0c898e31ab89978d88b0e1720fbfb7808 +"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.0": + version: 3.4.0 + resolution: "eslint-visitor-keys@npm:3.4.0" + checksum: 33159169462d3989321a1ec1e9aaaf6a24cc403d5d347e9886d1b5bfe18ffa1be73bdc6203143a28a606b142b1af49787f33cff0d6d0813eb5f2e8d2e1a6043c languageName: node linkType: hard -"eslint@npm:8.36.0": - version: 8.36.0 - resolution: "eslint@npm:8.36.0" +"eslint@npm:8.37.0": + version: 8.37.0 + resolution: "eslint@npm:8.37.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.4.0 - "@eslint/eslintrc": ^2.0.1 - "@eslint/js": 8.36.0 + "@eslint/eslintrc": ^2.0.2 + "@eslint/js": 8.37.0 "@humanwhocodes/config-array": ^0.11.8 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 @@ -7979,8 +7979,8 @@ __metadata: doctrine: ^3.0.0 escape-string-regexp: ^4.0.0 eslint-scope: ^7.1.1 - eslint-visitor-keys: ^3.3.0 - espree: ^9.5.0 + eslint-visitor-keys: ^3.4.0 + espree: ^9.5.1 esquery: ^1.4.2 esutils: ^2.0.2 fast-deep-equal: ^3.1.3 @@ -8007,18 +8007,18 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: e9a961fc3b3de5cff5a1cb2c92eeffaa7e155a715489e30b3e1e76f186bd1255e0481e09564f2094733c0b1dbd3453499fb72ae7c043c83156e11e6d965b2304 + checksum: 80f3d5cdce2d671f4794e392d234a78d039c347673defb0596268bd481e8f30a53d93c01ff4f66a546c87d97ab4122c0e9cafe1371f87cb03cee6b7d5aa97595 languageName: node linkType: hard -"espree@npm:^9.5.0": - version: 9.5.0 - resolution: "espree@npm:9.5.0" +"espree@npm:^9.5.1": + version: 9.5.1 + resolution: "espree@npm:9.5.1" dependencies: acorn: ^8.8.0 acorn-jsx: ^5.3.2 - eslint-visitor-keys: ^3.3.0 - checksum: a7f110aefb6407e0d3237aa635ab3cea87106ae63748dd23c67031afccc640d04c4209fca2daf16e2233c82efb505faead0fb84097478fd9cc6e8f8dd80bf99d + eslint-visitor-keys: ^3.4.0 + checksum: cdf6e43540433d917c4f2ee087c6e987b2063baa85a1d9cdaf51533d78275ebd5910c42154e7baf8e3e89804b386da0a2f7fad2264d8f04420e7506bf87b3b88 languageName: node linkType: hard @@ -9500,7 +9500,7 @@ __metadata: "@vibrant/core": 3.2.1-alpha.1 "@vibrant/quantizer-mmcq": 3.2.1-alpha.1 "@vue/web-component-wrapper": 1.3.0 - "@web/dev-server": 0.1.36 + "@web/dev-server": 0.1.37 "@web/dev-server-rollup": 0.4.0 "@webcomponents/scoped-custom-element-registry": 0.0.8 "@webcomponents/webcomponentsjs": 2.7.0 @@ -9517,7 +9517,7 @@ __metadata: deep-clone-simple: 1.1.1 deep-freeze: 0.0.1 del: 7.0.0 - eslint: 8.36.0 + eslint: 8.37.0 eslint-config-airbnb-base: 15.0.0 eslint-config-airbnb-typescript: 17.0.0 eslint-config-prettier: 8.8.0