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