n8n-editor-ui
Version:
Workflow Editor UI for n8n
357 lines (356 loc) • 14.6 kB
JavaScript
import { C as computed, Cn as toDisplayString, E as createCommentVNode, Gt as unref, It as ref, M as createVNode, P as defineComponent, T as createBlock, _t as watch, bt as withCtx, et as openBlock, j as createTextVNode, mt as useTemplateRef, vn as normalizeClass, w as createBaseVNode } from "./vue.runtime.esm-bundler-tP5dCd7J.js";
import { _t as useI18n } from "./_MapCache-ficiegRb.js";
import { $ as N8nInputLabel_default, Sn as N8nButton_default, f as N8nIconPicker_default, yn as N8nHeading_default, yt as N8nInput_default } from "./src-DgvumQTi.js";
import "./en-CF30SCh2.js";
import "./preload-helper-CR0ecmWK.js";
import { t as __plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BwBpWJRZ.js";
import { T as createEventBus } from "./truncate-B1HVeveJ.js";
import { m as useMessage, oa as useUIStore, v as useToast } from "./builder.store-sBTWwxRU.js";
import "./empty-BuGRxzl4.js";
import "./dialog-D5O6wJX0.js";
import "./sanitize-html-Cc45ZKm8.js";
import "./CalendarDate-zWqgZMlk.js";
import "./path-browserify-BtCDmZ3_.js";
import { ei as emptyChatModelsResponse } from "./constants-BbpucWL4.js";
import "./merge-k8vSyyXH.js";
import { g as assert, r as useRootStore } from "./_baseOrderBy-B_6CV8x6.js";
import "./dateformat-CM9k0--B.js";
import "./useDebounce-Bnb8W2LR.js";
import "./retry-dP46utx2.js";
import "./nodeIcon-DI2Acud1.js";
import "./NodeIcon-BVhrZNYI.js";
import { t as Modal_default } from "./Modal-CaRDt4OG.js";
import "./CredentialIcon-FEnE25SA.js";
import { p as TOOLS_SELECTOR_MODAL_KEY } from "./constants-DLTaaipl.js";
import { d as personalAgentDefaultIcon, g as fetchChatModelsApi, t as useChatStore, u as isLlmProviderModel } from "./chat.store-BGFxJU_3.js";
import "./fileUtils-D_SiS8no.js";
import { n as ToolsSelector_default, r as ModelSelector_default, t as useCustomAgent } from "./useCustomAgent-DBhdLpPp.js";
import "./ChatAgentAvatar-DMLTyAJz.js";
var AgentEditorModal_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "AgentEditorModal",
props: {
modalName: {},
data: {}
},
setup(__props) {
const props = __props;
const chatStore = useChatStore();
const i18n = useI18n();
const toast = useToast();
const message = useMessage();
const uiStore = useUIStore();
const modalBus = ref(createEventBus());
const { customAgent, isLoading: isLoadingCustomAgent } = useCustomAgent(props.data.agentId);
const name = ref("");
const description = ref("");
const systemPrompt = ref("");
const selectedModel = ref(null);
const isSaving = ref(false);
const isDeleting = ref(false);
const isOpened = ref(false);
const tools = ref([]);
const agents = ref(emptyChatModelsResponse);
const isLoadingAgents = ref(false);
const nameInputRef = useTemplateRef("nameInput");
const icon = ref(personalAgentDefaultIcon);
const agentSelectedCredentials = ref({});
const credentialIdForSelectedModelProvider = computed(() => selectedModel.value && agentMergedCredentials.value[selectedModel.value.provider]);
const selectedAgent = computed(() => selectedModel.value && chatStore.getAgent(selectedModel.value, { name: selectedModel.value.model }));
const isEditMode = computed(() => !!props.data.agentId);
const isLoadingAgent = computed(() => isEditMode.value && isLoadingCustomAgent.value);
const title = computed(() => isEditMode.value ? i18n.baseText("chatHub.agent.editor.title.edit") : i18n.baseText("chatHub.agent.editor.title.new"));
const saveButtonLabel = computed(() => isSaving.value ? i18n.baseText("chatHub.agent.editor.saving") : i18n.baseText("chatHub.agent.editor.save"));
const isValid = computed(() => {
return name.value.trim().length > 0 && systemPrompt.value.trim().length > 0 && selectedModel.value !== null && !!credentialIdForSelectedModelProvider.value;
});
const agentMergedCredentials = computed(() => {
return {
...props.data.credentials,
...agentSelectedCredentials.value
};
});
const canSelectTools = computed(() => selectedAgent.value?.metadata.capabilities.functionCalling ?? false);
modalBus.value.once("opened", () => {
isOpened.value = true;
});
watch(selectedAgent, (agent) => {
if (agent && !agent.metadata.capabilities.functionCalling) tools.value = [];
}, { immediate: true });
watch(customAgent, (agent) => {
if (!agent) return;
icon.value = agent.icon ?? personalAgentDefaultIcon;
name.value = agent.name;
description.value = agent.description ?? "";
systemPrompt.value = agent.systemPrompt;
selectedModel.value = {
provider: agent.provider,
model: agent.model
};
tools.value = agent.tools || [];
if (agent.credentialId) agentSelectedCredentials.value[agent.provider] = agent.credentialId;
}, { immediate: true });
watch([
isOpened,
isLoadingAgent,
nameInputRef
], ([opened, isLoading, nameInput]) => {
if (opened && !isLoading) nameInput?.focus();
}, {
immediate: true,
flush: "post"
});
watch(agentMergedCredentials, async (credentials) => {
if (credentials) {
isLoadingAgents.value = true;
try {
agents.value = await fetchChatModelsApi(useRootStore().restApiContext, { credentials });
} finally {
isLoadingAgents.value = false;
}
}
}, { immediate: true });
function onCredentialSelected(provider, credentialId) {
agentSelectedCredentials.value = {
...agentSelectedCredentials.value,
[provider]: credentialId
};
}
function onModelChange(model) {
assert(isLlmProviderModel(model));
selectedModel.value = model;
}
async function onSave() {
if (!isValid.value || isSaving.value) return;
isSaving.value = true;
try {
assert(selectedModel.value);
assert(credentialIdForSelectedModelProvider.value);
const payload = {
name: name.value.trim(),
description: description.value.trim() || void 0,
systemPrompt: systemPrompt.value.trim(),
...selectedModel.value,
credentialId: credentialIdForSelectedModelProvider.value,
tools: tools.value,
icon: icon.value
};
if (isEditMode.value && props.data.agentId) {
await chatStore.updateCustomAgent(props.data.agentId, payload, props.data.credentials);
toast.showMessage({
title: i18n.baseText("chatHub.agent.editor.success.update"),
type: "success"
});
} else {
const agent = await chatStore.createCustomAgent(payload, props.data.credentials);
props.data.onCreateCustomAgent?.(agent);
toast.showMessage({
title: i18n.baseText("chatHub.agent.editor.success.create"),
type: "success"
});
}
modalBus.value.emit("close");
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "";
toast.showError(error, i18n.baseText("chatHub.agent.editor.error.save"), errorMessage);
} finally {
isSaving.value = false;
}
}
async function onDelete() {
if (!isEditMode.value || !props.data.agentId || isDeleting.value) return;
if (await message.confirm(i18n.baseText("chatHub.agent.editor.delete.confirm.message"), i18n.baseText("chatHub.agent.editor.delete.confirm.title"), {
confirmButtonText: i18n.baseText("chatHub.agent.editor.delete.confirm.button"),
cancelButtonText: i18n.baseText("chatHub.agent.editor.delete.cancel.button"),
type: "warning"
}) !== "confirm") return;
isDeleting.value = true;
try {
await chatStore.deleteCustomAgent(props.data.agentId, props.data.credentials);
toast.showMessage({
title: i18n.baseText("chatHub.agent.editor.success.delete"),
type: "success"
});
props.data.onClose?.();
modalBus.value.emit("close");
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "";
toast.showError(error, i18n.baseText("chatHub.agent.editor.error.delete"), errorMessage);
} finally {
isDeleting.value = false;
}
}
function onSelectTools() {
uiStore.openModalWithData({
name: TOOLS_SELECTOR_MODAL_KEY,
data: {
selected: tools.value,
onConfirm: (newTools) => {
tools.value = newTools;
}
}
});
}
return (_ctx, _cache) => {
return openBlock(), createBlock(Modal_default, {
name: _ctx.modalName,
"event-bus": modalBus.value,
width: "600px",
center: true,
loading: isLoadingAgent.value,
"max-width": "90%",
"min-height": "400px"
}, {
header: withCtx(() => [createBaseVNode("div", { class: normalizeClass(_ctx.$style.header) }, [createVNode(unref(N8nHeading_default), {
tag: "h2",
size: "large"
}, {
default: withCtx(() => [createTextVNode(toDisplayString(title.value), 1)]),
_: 1
}), isEditMode.value ? (openBlock(), createBlock(unref(N8nButton_default), {
key: 0,
type: "secondary",
icon: "trash-2",
disabled: isDeleting.value,
loading: isDeleting.value,
onClick: onDelete
}, null, 8, ["disabled", "loading"])) : createCommentVNode("", true)], 2)]),
content: withCtx(() => [createBaseVNode("div", { class: normalizeClass(_ctx.$style.content) }, [
createVNode(unref(N8nInputLabel_default), {
"input-name": "agent-name",
label: unref(i18n).baseText("chatHub.agent.editor.name.label"),
required: true
}, {
default: withCtx(() => [createBaseVNode("div", { class: normalizeClass(_ctx.$style.agentName) }, [createVNode(unref(N8nIconPicker_default), {
modelValue: icon.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => icon.value = $event),
"button-tooltip": unref(i18n).baseText("chatHub.agent.editor.iconPicker.button.tooltip")
}, null, 8, ["modelValue", "button-tooltip"]), createVNode(unref(N8nInput_default), {
id: "agent-name",
ref: "nameInput",
modelValue: name.value,
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => name.value = $event),
placeholder: unref(i18n).baseText("chatHub.agent.editor.name.placeholder"),
maxlength: 128,
class: normalizeClass(_ctx.$style.agentNameInput)
}, null, 8, [
"modelValue",
"placeholder",
"class"
])], 2)]),
_: 1
}, 8, ["label"]),
createVNode(unref(N8nInputLabel_default), {
"input-name": "agent-description",
label: unref(i18n).baseText("chatHub.agent.editor.description.label")
}, {
default: withCtx(() => [createVNode(unref(N8nInput_default), {
id: "agent-description",
modelValue: description.value,
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => description.value = $event),
type: "textarea",
placeholder: unref(i18n).baseText("chatHub.agent.editor.description.placeholder"),
maxlength: 512,
rows: 3,
class: normalizeClass(_ctx.$style.input)
}, null, 8, [
"modelValue",
"placeholder",
"class"
])]),
_: 1
}, 8, ["label"]),
createVNode(unref(N8nInputLabel_default), {
"input-name": "agent-system-prompt",
label: unref(i18n).baseText("chatHub.agent.editor.systemPrompt.label"),
required: true
}, {
default: withCtx(() => [createVNode(unref(N8nInput_default), {
id: "agent-system-prompt",
modelValue: systemPrompt.value,
"onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => systemPrompt.value = $event),
type: "textarea",
placeholder: unref(i18n).baseText("chatHub.agent.editor.systemPrompt.placeholder"),
rows: 6,
class: normalizeClass(_ctx.$style.input)
}, null, 8, [
"modelValue",
"placeholder",
"class"
])]),
_: 1
}, 8, ["label"]),
createBaseVNode("div", { class: normalizeClass(_ctx.$style.row) }, [createVNode(unref(N8nInputLabel_default), {
"input-name": "agent-model",
class: normalizeClass(_ctx.$style.input),
label: unref(i18n).baseText("chatHub.agent.editor.model.label"),
required: true
}, {
default: withCtx(() => [createVNode(ModelSelector_default, {
"selected-agent": selectedAgent.value,
"include-custom-agents": false,
credentials: agentMergedCredentials.value,
agents: agents.value,
"is-loading": isLoadingAgents.value,
"warn-missing-credentials": "",
onChange: onModelChange,
onSelectCredential: onCredentialSelected
}, null, 8, [
"selected-agent",
"credentials",
"agents",
"is-loading"
])]),
_: 1
}, 8, ["class", "label"]), createVNode(unref(N8nInputLabel_default), {
"input-name": "agent-model",
class: normalizeClass(_ctx.$style.input),
label: unref(i18n).baseText("chatHub.agent.editor.tools.label"),
required: false
}, {
default: withCtx(() => [createBaseVNode("div", null, [createVNode(ToolsSelector_default, {
disabled: !canSelectTools.value,
"disabled-tooltip": canSelectTools.value ? void 0 : unref(i18n).baseText("chatHub.tools.selector.disabled.tooltip"),
selected: tools.value,
onClick: onSelectTools
}, null, 8, [
"disabled",
"disabled-tooltip",
"selected"
])])]),
_: 1
}, 8, ["class", "label"])], 2)
], 2)]),
footer: withCtx(() => [createBaseVNode("div", { class: normalizeClass(_ctx.$style.footer) }, [createVNode(unref(N8nButton_default), {
type: "secondary",
onClick: _cache[4] || (_cache[4] = ($event) => modalBus.value.emit("close"))
}, {
default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("chatHub.tools.editor.cancel")), 1)]),
_: 1
}), createVNode(unref(N8nButton_default), {
type: "primary",
disabled: !isValid.value || isSaving.value,
onClick: onSave
}, {
default: withCtx(() => [createTextVNode(toDisplayString(saveButtonLabel.value), 1)]),
_: 1
}, 8, ["disabled"])], 2)]),
_: 1
}, 8, [
"name",
"event-bus",
"loading"
]);
};
}
});
var AgentEditorModal_vue_vue_type_style_index_0_lang_module_default = {
header: "_header_8gx01_123",
content: "_content_8gx01_131",
input: "_input_8gx01_138",
agentName: "_agentName_8gx01_142",
agentNameInput: "_agentNameInput_8gx01_148",
row: "_row_8gx01_152",
footer: "_footer_8gx01_158"
};
var AgentEditorModal_default = /* @__PURE__ */ __plugin_vue_export_helper_default(AgentEditorModal_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": AgentEditorModal_vue_vue_type_style_index_0_lang_module_default }]]);
export { AgentEditorModal_default as default };