mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Assist pipeline language voice (#16255)
* Update types * Split form into multiple components * Improve design * Send all data * Update wording
This commit is contained in:
parent
65161ce581
commit
ea0f29782d
@ -6,18 +6,26 @@ import type { SpeechMetadata } from "./stt";
|
||||
export interface AssistPipeline {
|
||||
id: string;
|
||||
conversation_engine: string;
|
||||
conversation_language: string | null;
|
||||
language: string;
|
||||
name: string;
|
||||
stt_engine: string;
|
||||
tts_engine: string;
|
||||
stt_engine: string | null;
|
||||
stt_language: string | null;
|
||||
tts_engine: string | null;
|
||||
tts_language: string | null;
|
||||
tts_voice: string | null;
|
||||
}
|
||||
|
||||
export interface AssistPipelineMutableParams {
|
||||
conversation_engine: string;
|
||||
conversation_language?: string | null;
|
||||
language: string;
|
||||
name: string;
|
||||
stt_engine: string;
|
||||
tts_engine: string;
|
||||
stt_engine?: string | null;
|
||||
stt_language?: string | null;
|
||||
tts_engine?: string | null;
|
||||
tts_language?: string | null;
|
||||
tts_voice?: string | null;
|
||||
}
|
||||
|
||||
export interface assistRunListing {
|
||||
@ -274,7 +282,7 @@ export const createAssistPipeline = (
|
||||
export const updateAssistPipeline = (
|
||||
hass: HomeAssistant,
|
||||
pipeline_id: string,
|
||||
pipeline: Partial<AssistPipelineMutableParams>
|
||||
pipeline: AssistPipelineMutableParams
|
||||
) =>
|
||||
hass.callWS<AssistPipeline>({
|
||||
type: "assist_pipeline/pipeline/update",
|
||||
|
@ -0,0 +1,106 @@
|
||||
import { css, CSSResultGroup, html, LitElement } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { SchemaUnion } from "../../../../components/ha-form/types";
|
||||
import { AssistPipeline } from "../../../../data/assist_pipeline";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
|
||||
@customElement("assist-pipeline-detail-config")
|
||||
export class AssistPipelineDetailConfig extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public data?: Partial<AssistPipeline>;
|
||||
|
||||
@property() public error?: Record<string, string>;
|
||||
|
||||
@property() public supportedLanguages?: string[];
|
||||
|
||||
private _schema = memoizeOne(
|
||||
(supportedLanguages?: string[]) =>
|
||||
[
|
||||
{
|
||||
name: "",
|
||||
type: "grid",
|
||||
schema: [
|
||||
{
|
||||
name: "name",
|
||||
required: true,
|
||||
selector: {
|
||||
text: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "language",
|
||||
required: true,
|
||||
selector: {
|
||||
language: {
|
||||
languages: supportedLanguages ?? [],
|
||||
},
|
||||
},
|
||||
},
|
||||
] as const,
|
||||
},
|
||||
] as const
|
||||
);
|
||||
|
||||
private _computeLabel = (
|
||||
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||
): string =>
|
||||
this.hass.localize(
|
||||
`ui.panel.config.voice_assistants.assistants.pipeline.detail.form.${schema.name}`
|
||||
);
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<div class="section">
|
||||
<div class="intro">
|
||||
<h3>Configuration</h3>
|
||||
<p>Main configuration of your assistant</p>
|
||||
</div>
|
||||
<ha-form
|
||||
.schema=${this._schema(this.supportedLanguages)}
|
||||
.data=${this.data}
|
||||
.error=${this.error}
|
||||
.hass=${this.hass}
|
||||
.computeLabel=${this._computeLabel}
|
||||
></ha-form>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
.section {
|
||||
border: 1px solid var(--divider-color);
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
padding: 16px;
|
||||
}
|
||||
.intro {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
h3 {
|
||||
font-weight: normal;
|
||||
font-size: 22px;
|
||||
line-height: 28px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
p {
|
||||
font-weight: normal;
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"assist-pipeline-detail-config": AssistPipelineDetailConfig;
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
import { css, CSSResultGroup, html, LitElement } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { SchemaUnion } from "../../../../components/ha-form/types";
|
||||
import { AssistPipeline } from "../../../../data/assist_pipeline";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
|
||||
@customElement("assist-pipeline-detail-conversation")
|
||||
export class AssistPipelineDetailConversation extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public data?: Partial<AssistPipeline>;
|
||||
|
||||
@property() public error?: Record<string, string>;
|
||||
|
||||
private _schema = memoizeOne(
|
||||
(language?: string) =>
|
||||
[
|
||||
{
|
||||
name: "",
|
||||
type: "grid",
|
||||
schema: [
|
||||
{
|
||||
name: "conversation_engine",
|
||||
required: true,
|
||||
selector: {
|
||||
conversation_agent: {
|
||||
language,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "conversation_language",
|
||||
selector: {
|
||||
text: {},
|
||||
},
|
||||
},
|
||||
] as const,
|
||||
},
|
||||
] as const
|
||||
);
|
||||
|
||||
private _computeLabel = (
|
||||
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||
): string =>
|
||||
this.hass.localize(
|
||||
`ui.panel.config.voice_assistants.assistants.pipeline.detail.form.${schema.name}`
|
||||
);
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<div class="section">
|
||||
<div class="intro">
|
||||
<h3>Conversation agent</h3>
|
||||
<p>
|
||||
The conversation agent is the brains of your voice assistant and
|
||||
will process the incoming commands.
|
||||
</p>
|
||||
</div>
|
||||
<ha-form
|
||||
.schema=${this._schema(this.data?.language)}
|
||||
.data=${this.data}
|
||||
.error=${this.error}
|
||||
.hass=${this.hass}
|
||||
.computeLabel=${this._computeLabel}
|
||||
></ha-form>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
.section {
|
||||
border: 1px solid var(--divider-color);
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
padding: 16px;
|
||||
}
|
||||
.intro {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
h3 {
|
||||
font-weight: normal;
|
||||
font-size: 22px;
|
||||
line-height: 28px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
p {
|
||||
font-weight: normal;
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"assist-pipeline-detail-conversation": AssistPipelineDetailConversation;
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
import { css, CSSResultGroup, html, LitElement } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { SchemaUnion } from "../../../../components/ha-form/types";
|
||||
import { AssistPipeline } from "../../../../data/assist_pipeline";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
|
||||
@customElement("assist-pipeline-detail-stt")
|
||||
export class AssistPipelineDetailSTT extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public data?: Partial<AssistPipeline>;
|
||||
|
||||
@property() public error?: Record<string, string>;
|
||||
|
||||
private _schema = memoizeOne(
|
||||
(language?: string) =>
|
||||
[
|
||||
{
|
||||
name: "",
|
||||
type: "grid",
|
||||
schema: [
|
||||
{
|
||||
name: "stt_engine",
|
||||
selector: {
|
||||
stt: {
|
||||
language,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "stt_language",
|
||||
selector: {
|
||||
text: {},
|
||||
},
|
||||
},
|
||||
] as const,
|
||||
},
|
||||
] as const
|
||||
);
|
||||
|
||||
private _computeLabel = (
|
||||
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||
): string =>
|
||||
this.hass.localize(
|
||||
`ui.panel.config.voice_assistants.assistants.pipeline.detail.form.${schema.name}`
|
||||
);
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<div class="section">
|
||||
<div class="intro">
|
||||
<h3>Speech-to-text</h3>
|
||||
<p>
|
||||
When you are using the pipeline as a voice assistant, the
|
||||
speech-to-text engine turns your voice command into text.
|
||||
</p>
|
||||
</div>
|
||||
<ha-form
|
||||
.schema=${this._schema(this.data?.language)}
|
||||
.data=${this.data}
|
||||
.error=${this.error}
|
||||
.hass=${this.hass}
|
||||
.computeLabel=${this._computeLabel}
|
||||
></ha-form>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
.section {
|
||||
border: 1px solid var(--divider-color);
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
padding: 16px;
|
||||
}
|
||||
.intro {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
h3 {
|
||||
font-weight: normal;
|
||||
font-size: 22px;
|
||||
line-height: 28px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
p {
|
||||
font-weight: normal;
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"assist-pipeline-detail-stt": AssistPipelineDetailSTT;
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
import { css, CSSResultGroup, html, LitElement } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { SchemaUnion } from "../../../../components/ha-form/types";
|
||||
import { AssistPipeline } from "../../../../data/assist_pipeline";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
|
||||
@customElement("assist-pipeline-detail-tts")
|
||||
export class AssistPipelineDetailTTS extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public data?: Partial<AssistPipeline>;
|
||||
|
||||
@property() public error?: Record<string, string>;
|
||||
|
||||
private _schema = memoizeOne(
|
||||
(language?: string) =>
|
||||
[
|
||||
{
|
||||
name: "",
|
||||
type: "grid",
|
||||
schema: [
|
||||
{
|
||||
name: "tts_engine",
|
||||
selector: {
|
||||
tts: {
|
||||
language,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "tts_language",
|
||||
selector: {
|
||||
text: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "tts_voice",
|
||||
selector: {
|
||||
text: {},
|
||||
},
|
||||
},
|
||||
] as const,
|
||||
},
|
||||
] as const
|
||||
);
|
||||
|
||||
private _computeLabel = (
|
||||
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||
): string =>
|
||||
this.hass.localize(
|
||||
`ui.panel.config.voice_assistants.assistants.pipeline.detail.form.${schema.name}`
|
||||
);
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<div class="section">
|
||||
<div class="intro">
|
||||
<h3>Text-to-speech</h3>
|
||||
<p>
|
||||
When you are using the pipeline as a voice assistant, the
|
||||
text-to-speech engine turns the conversation text responses into
|
||||
audio.
|
||||
</p>
|
||||
</div>
|
||||
<ha-form
|
||||
.schema=${this._schema(this.data?.language)}
|
||||
.data=${this.data}
|
||||
.error=${this.error}
|
||||
.hass=${this.hass}
|
||||
.computeLabel=${this._computeLabel}
|
||||
></ha-form>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
.section {
|
||||
border: 1px solid var(--divider-color);
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
padding: 16px;
|
||||
}
|
||||
.intro {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
h3 {
|
||||
font-weight: normal;
|
||||
font-size: 22px;
|
||||
line-height: 28px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
p {
|
||||
font-weight: normal;
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"assist-pipeline-detail-tts": AssistPipelineDetailTTS;
|
||||
}
|
||||
}
|
@ -1,11 +1,9 @@
|
||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import "../../../components/ha-button";
|
||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||
import "../../../components/ha-form/ha-form";
|
||||
import { SchemaUnion } from "../../../components/ha-form/types";
|
||||
import {
|
||||
AssistPipeline,
|
||||
AssistPipelineMutableParams,
|
||||
@ -13,6 +11,10 @@ import {
|
||||
} from "../../../data/assist_pipeline";
|
||||
import { haStyleDialog } from "../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import "./assist-pipeline-detail/assist-pipeline-detail-conversation";
|
||||
import "./assist-pipeline-detail/assist-pipeline-detail-config";
|
||||
import "./assist-pipeline-detail/assist-pipeline-detail-stt";
|
||||
import "./assist-pipeline-detail/assist-pipeline-detail-tts";
|
||||
import "./debug/assist-render-pipeline-events";
|
||||
import { VoiceAssistantPipelineDetailsDialogParams } from "./show-dialog-voice-assistant-pipeline-detail";
|
||||
|
||||
@ -79,14 +81,31 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement {
|
||||
)}
|
||||
>
|
||||
<div>
|
||||
<ha-form
|
||||
.schema=${this._schema(this._supportedLanguages)}
|
||||
.data=${this._data}
|
||||
<assist-pipeline-detail-config
|
||||
.hass=${this.hass}
|
||||
.data=${this._data}
|
||||
.error=${this._error}
|
||||
.computeLabel=${this._computeLabel}
|
||||
.supportedLanguages=${this._supportedLanguages}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-form>
|
||||
></assist-pipeline-detail-config>
|
||||
<assist-pipeline-detail-conversation
|
||||
.hass=${this.hass}
|
||||
.data=${this._data}
|
||||
.error=${this._error}
|
||||
@value-changed=${this._valueChanged}
|
||||
></assist-pipeline-detail-conversation>
|
||||
<assist-pipeline-detail-stt
|
||||
.hass=${this.hass}
|
||||
.data=${this._data}
|
||||
.error=${this._error}
|
||||
@value-changed=${this._valueChanged}
|
||||
></assist-pipeline-detail-stt>
|
||||
<assist-pipeline-detail-tts
|
||||
.hass=${this.hass}
|
||||
.data=${this._data}
|
||||
.error=${this._error}
|
||||
@value-changed=${this._valueChanged}
|
||||
></assist-pipeline-detail-tts>
|
||||
</div>
|
||||
${this._params.pipeline?.id
|
||||
? html`
|
||||
@ -131,57 +150,6 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
private _schema = memoizeOne(
|
||||
(supportedLanguages: string[]) =>
|
||||
[
|
||||
{
|
||||
name: "name",
|
||||
required: true,
|
||||
selector: {
|
||||
text: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "language",
|
||||
required: true,
|
||||
selector: {
|
||||
language: {
|
||||
languages: supportedLanguages,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "conversation_engine",
|
||||
required: true,
|
||||
selector: {
|
||||
conversation_agent: {},
|
||||
},
|
||||
context: { language: "language" },
|
||||
},
|
||||
{
|
||||
name: "stt_engine",
|
||||
selector: {
|
||||
stt: {},
|
||||
},
|
||||
context: { language: "language" },
|
||||
},
|
||||
{
|
||||
name: "tts_engine",
|
||||
selector: {
|
||||
tts: {},
|
||||
},
|
||||
context: { language: "language" },
|
||||
},
|
||||
] as const
|
||||
);
|
||||
|
||||
private _computeLabel = (
|
||||
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||
): string =>
|
||||
this.hass.localize(
|
||||
`ui.panel.config.voice_assistants.assistants.pipeline.detail.form.${schema.name}`
|
||||
);
|
||||
|
||||
private _valueChanged(ev: CustomEvent) {
|
||||
this._error = undefined;
|
||||
const value = ev.detail.value;
|
||||
@ -192,12 +160,17 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement {
|
||||
this._submitting = true;
|
||||
try {
|
||||
if (this._params!.pipeline?.id) {
|
||||
const values: Partial<AssistPipelineMutableParams> = {
|
||||
name: this._data!.name,
|
||||
conversation_engine: this._data!.conversation_engine,
|
||||
language: this._data!.language,
|
||||
stt_engine: this._data!.stt_engine,
|
||||
tts_engine: this._data!.tts_engine,
|
||||
const data = this._data!;
|
||||
const values: AssistPipelineMutableParams = {
|
||||
name: data.name!,
|
||||
language: data.language!,
|
||||
conversation_engine: data.conversation_engine!,
|
||||
conversation_language: data.conversation_language,
|
||||
stt_engine: data.stt_engine,
|
||||
stt_language: data.stt_language,
|
||||
tts_engine: data.tts_engine,
|
||||
tts_language: data.tts_language,
|
||||
tts_voice: data.tts_voice,
|
||||
};
|
||||
await this._params!.updatePipeline(values);
|
||||
} else {
|
||||
@ -239,7 +212,18 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement {
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [haStyleDialog, css``];
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
assist-pipeline-detail-config,
|
||||
assist-pipeline-detail-conversation,
|
||||
assist-pipeline-detail-stt,
|
||||
assist-pipeline-detail-tts {
|
||||
margin-bottom: 16px;
|
||||
display: block;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,7 @@ export interface VoiceAssistantPipelineDetailsDialogParams {
|
||||
pipeline?: AssistPipeline;
|
||||
preferred?: boolean;
|
||||
createPipeline: (values: AssistPipelineMutableParams) => Promise<unknown>;
|
||||
updatePipeline: (
|
||||
updates: Partial<AssistPipelineMutableParams>
|
||||
) => Promise<unknown>;
|
||||
updatePipeline: (updates: AssistPipelineMutableParams) => Promise<unknown>;
|
||||
setPipelinePreferred: () => Promise<unknown>;
|
||||
deletePipeline: () => Promise<boolean>;
|
||||
}
|
||||
|
@ -2030,9 +2030,13 @@
|
||||
"form": {
|
||||
"name": "Name",
|
||||
"conversation_engine": "Conversation agent",
|
||||
"conversation_language": "[%key:ui::panel::config::voice_assistants::assistants::pipeline::detail::form::language%]",
|
||||
"language": "Language",
|
||||
"stt_engine": "Speech to text",
|
||||
"tts_engine": "Text to speech"
|
||||
"stt_language": "[%key:ui::panel::config::voice_assistants::assistants::pipeline::detail::form::language%]",
|
||||
"tts_engine": "Text to speech",
|
||||
"tts_language": "[%key:ui::panel::config::voice_assistants::assistants::pipeline::detail::form::language%]",
|
||||
"tts_voice": "Voice"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user