Add AI Task to suggest automation name

pull/25778/head
Paulus Schoutsen 2025-06-13 10:35:45 -04:00
parent 67c7a3931f
commit ac2476babd
3 changed files with 84 additions and 3 deletions

39
src/data/ai_task.ts Normal file
View File

@ -0,0 +1,39 @@
import type { HomeAssistant } from "../types";
export interface AITaskPreferences {
gen_text_summary_entity_id: string | null;
gen_text_generate_entity_id: string | null;
}
export interface GenTextTaskResult {
conversation_id: string;
result: string;
}
export const fetchAITaskPreferences = (hass: HomeAssistant) =>
hass.callWS<AITaskPreferences>({
type: "ai_task/preferences/get",
});
export const saveAITaskPreferences = (
hass: HomeAssistant,
preferences: Partial<AITaskPreferences>
) =>
hass.callWS<AITaskPreferences>({
type: "ai_task/preferences/set",
...preferences,
});
export const generateTextAITask = (
hass: HomeAssistant,
task: {
task_name: string;
entity_id?: string;
task_type: "summary" | "generate";
prompt: string;
}
) =>
hass.callWS<GenTextTaskResult>({
type: "ai_task/generate_text",
...task,
});

View File

@ -1,8 +1,9 @@
import "@material/mwc-button";
import type { CSSResultGroup } from "lit";
import type { CSSResultGroup, PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { mdiClose, mdiPlus } from "@mdi/js";
import { mdiClose, mdiPlus, mdiStarFourPoints } from "@mdi/js";
import { dump } from "js-yaml";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-alert";
import "../../../../components/ha-domain-icon";
@ -24,6 +25,11 @@ import type {
SaveDialogParams,
} from "./show-dialog-automation-save";
import { supportsMarkdownHelper } from "../../../../common/translations/markdown_support";
import {
fetchAITaskPreferences,
generateTextAITask,
} from "../../../../data/ai_task";
import { isComponentLoaded } from "../../../../common/config/is_component_loaded";
@customElement("ha-dialog-automation-save")
class DialogAutomationSave extends LitElement implements HassDialog {
@ -37,6 +43,8 @@ class DialogAutomationSave extends LitElement implements HassDialog {
@state() private _entryUpdates!: EntityRegistryUpdate;
@state() private _canSuggest = false;
private _params!: SaveDialogParams;
private _newName?: string;
@ -81,6 +89,15 @@ class DialogAutomationSave extends LitElement implements HassDialog {
return true;
}
protected firstUpdated(changedProperties: PropertyValues): void {
super.firstUpdated(changedProperties);
if (isComponentLoaded(this.hass, "ai_task")) {
fetchAITaskPreferences(this.hass).then((prefs) => {
this._canSuggest = prefs.gen_text_summary_entity_id !== null;
});
}
}
protected _renderOptionalChip(id: string, label: string) {
if (this._visibleOptionals.includes(id)) {
return nothing;
@ -250,6 +267,16 @@ class DialogAutomationSave extends LitElement implements HassDialog {
.path=${mdiClose}
></ha-icon-button>
<span slot="title">${this._params.title || title}</span>
${this._canSuggest
? html`
<ha-icon-button
slot="actionItems"
.label=${this.hass.localize("ui.common.suggest_ai")}
.path=${mdiStarFourPoints}
@click=${this._suggest}
></ha-icon-button>
`
: nothing}
</ha-dialog-header>
${this._error
? html`<ha-alert alert-type="error"
@ -313,6 +340,20 @@ class DialogAutomationSave extends LitElement implements HassDialog {
this.closeDialog();
}
private async _suggest() {
const result = await generateTextAITask(this.hass, {
task_name: "frontend:automation:save",
task_type: "summary",
prompt: `Give me a name for the following Home Assistant automation.
The name should be short, descriptive, and written in the language ${this.hass.language}.
${dump(this._params.config)}
`,
});
this._newName = result.result.trim();
this.requestUpdate();
}
private async _save(): Promise<void> {
if (!this._newName) {
this._error = "Name is required";

View File

@ -380,7 +380,8 @@
"replace": "Replace",
"append": "Append",
"supports_markdown": "Supports {markdown_help_link}",
"markdown": "Markdown"
"markdown": "Markdown",
"suggest_ai": "Suggest with AI"
},
"components": {
"selectors": {