node-red-contrib-knx-ultimate 6.2.1 → 6.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -4
- package/nodes/knxUltimateAI.html +207 -207
- package/nodes/knxUltimateAI.js +14 -14
- package/nodes/locales/de/knxUltimateAI.html +9 -31
- package/nodes/locales/en/knxUltimateAI.html +9 -30
- package/nodes/locales/es/knxUltimateAI.html +9 -31
- package/nodes/locales/fr/knxUltimateAI.html +9 -31
- package/nodes/locales/it/knxUltimateAI.html +9 -30
- package/nodes/locales/zh-CN/knxUltimateAI.html +9 -31
- package/package.json +2 -2
package/nodes/knxUltimateAI.html
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/htmlUtils.js"></script>
|
|
2
2
|
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/KNXAIChatAdapterMappings.js"></script>
|
|
3
3
|
<style type="text/css">
|
|
4
|
-
#knx-ai-models-status {
|
|
5
|
-
margin-top: 6px;
|
|
6
|
-
margin-bottom: 6px;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
4
|
#knx-ai-ollama-install-row {
|
|
10
5
|
align-items: flex-start;
|
|
11
6
|
}
|
|
@@ -26,18 +21,29 @@
|
|
|
26
21
|
margin: 0 !important;
|
|
27
22
|
}
|
|
28
23
|
|
|
29
|
-
.knx-ai-chat-adapter-
|
|
30
|
-
display: block;
|
|
24
|
+
.knx-ai-chat-adapter-editor {
|
|
31
25
|
width: 100% !important;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
min-height: 190px;
|
|
26
|
+
height: 220px;
|
|
27
|
+
min-height: 180px;
|
|
35
28
|
box-sizing: border-box;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#node-input-chatInputCode-editor .monaco-editor,
|
|
32
|
+
#node-input-chatInputCode-editor .monaco-editor-background,
|
|
33
|
+
#node-input-chatInputCode-editor .monaco-editor .margin,
|
|
34
|
+
#node-input-chatInputCode-editor .monaco-editor .overflow-guard,
|
|
35
|
+
#node-input-chatInputCode-editor .monaco-editor .lines-content,
|
|
36
|
+
#node-input-chatInputCode-editor .monaco-editor .editor-scrollable {
|
|
37
|
+
background-color: #e8f5e9 !important;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#node-input-chatOutputCode-editor .monaco-editor,
|
|
41
|
+
#node-input-chatOutputCode-editor .monaco-editor-background,
|
|
42
|
+
#node-input-chatOutputCode-editor .monaco-editor .margin,
|
|
43
|
+
#node-input-chatOutputCode-editor .monaco-editor .overflow-guard,
|
|
44
|
+
#node-input-chatOutputCode-editor .monaco-editor .lines-content,
|
|
45
|
+
#node-input-chatOutputCode-editor .monaco-editor .editor-scrollable {
|
|
46
|
+
background-color: #fffde7 !important;
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
#knx-ai-accordion {
|
|
@@ -93,12 +99,6 @@
|
|
|
93
99
|
display: block;
|
|
94
100
|
}
|
|
95
101
|
|
|
96
|
-
#knx-ai-ollama-steps,
|
|
97
|
-
#knx-ai-ollama-empty-help {
|
|
98
|
-
margin-left: 290px;
|
|
99
|
-
margin-top: 6px;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
102
|
@media (max-width: 900px) {
|
|
103
103
|
#knx-ai-ollama-install-row>label {
|
|
104
104
|
width: 100% !important;
|
|
@@ -110,10 +110,6 @@
|
|
|
110
110
|
max-width: 100%;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
#knx-ai-ollama-steps,
|
|
114
|
-
#knx-ai-ollama-empty-help {
|
|
115
|
-
margin-left: 0;
|
|
116
|
-
}
|
|
117
113
|
}
|
|
118
114
|
</style>
|
|
119
115
|
|
|
@@ -126,37 +122,19 @@
|
|
|
126
122
|
name: { value: "KNX AI", required: false },
|
|
127
123
|
topic: { value: "", required: false },
|
|
128
124
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
notifywrite: { value: true },
|
|
132
|
-
|
|
133
|
-
analysisWindowSec: { value: 120, required: true, validate: RED.validators.number() },
|
|
134
|
-
historyWindowSec: { value: 600, required: true, validate: RED.validators.number() },
|
|
125
|
+
analysisWindowSec: { value: 120 },
|
|
126
|
+
historyWindowSec: { value: 600 },
|
|
135
127
|
historyStoreToDisk: { value: true },
|
|
136
|
-
historyStoreRetentionDays: { value: 10
|
|
137
|
-
emitIntervalSec: { value: 0
|
|
138
|
-
topN: { value: 10
|
|
139
|
-
maxEvents: { value: 50000
|
|
140
|
-
|
|
141
|
-
rateWindowSec: { value: 10, required: true, validate: RED.validators.number() },
|
|
142
|
-
maxTelegramPerSecOverall: { value: 0, required: true, validate: RED.validators.number() },
|
|
143
|
-
maxTelegramPerSecPerGA: { value: 0, required: true, validate: RED.validators.number() },
|
|
144
|
-
|
|
145
|
-
flapWindowSec: { value: 30, required: true, validate: RED.validators.number() },
|
|
146
|
-
flapMaxChanges: { value: 0, required: true, validate: RED.validators.number() },
|
|
147
|
-
|
|
148
|
-
enablePattern: { value: true },
|
|
149
|
-
patternMaxLagMs: { value: 1500, required: true, validate: RED.validators.number() },
|
|
150
|
-
patternMinCount: { value: 8, required: true, validate: RED.validators.number() },
|
|
128
|
+
historyStoreRetentionDays: { value: 10 },
|
|
129
|
+
emitIntervalSec: { value: 0 },
|
|
130
|
+
topN: { value: 10 },
|
|
131
|
+
maxEvents: { value: 50000 },
|
|
151
132
|
|
|
152
133
|
llmEnabled: { value: false },
|
|
153
134
|
llmProvider: { value: "openai_compat" },
|
|
154
135
|
llmBaseUrl: { value: "https://api.openai.com/v1/chat/completions" },
|
|
155
136
|
llmModel: { value: "gpt-5.4" },
|
|
156
|
-
llmSystemPrompt: { value: "" },
|
|
157
|
-
llmIncludeRaw: { value: false },
|
|
158
137
|
llmIncludeFlowContext: { value: true },
|
|
159
|
-
llmIncludeDocsSnippets: { value: true },
|
|
160
138
|
llmDocsLanguage: { value: "en" },
|
|
161
139
|
llmAllowKnxCommands: { value: false },
|
|
162
140
|
llmRequireCommandConfirmation: { value: true },
|
|
@@ -165,11 +143,11 @@
|
|
|
165
143
|
chatOutputCode: { value: "" },
|
|
166
144
|
proactiveEnabled: { value: false },
|
|
167
145
|
proactiveRecipient: { value: "" },
|
|
168
|
-
proactiveOpenMinutes: { value: 120
|
|
169
|
-
proactiveCooldownMinutes: { value: 360
|
|
146
|
+
proactiveOpenMinutes: { value: 120 },
|
|
147
|
+
proactiveCooldownMinutes: { value: 360 },
|
|
170
148
|
proactiveQuietStart: { value: "23:00" },
|
|
171
149
|
proactiveQuietEnd: { value: "07:00" },
|
|
172
|
-
homeMemoryMaxKb: { value: 256
|
|
150
|
+
homeMemoryMaxKb: { value: 256 },
|
|
173
151
|
aiEducation: { value: "" }
|
|
174
152
|
},
|
|
175
153
|
credentials: {
|
|
@@ -192,6 +170,7 @@
|
|
|
192
170
|
paletteLabel: "KNX AI",
|
|
193
171
|
oneditprepare: function () {
|
|
194
172
|
try { RED.sidebar.show("help"); } catch (error) { }
|
|
173
|
+
const node = this;
|
|
195
174
|
const OPENAI_COMPAT_DEFAULT_CHAT_URL = "https://api.openai.com/v1/chat/completions";
|
|
196
175
|
const OLLAMA_DEFAULT_CHAT_URL = "http://localhost:11434/api/chat";
|
|
197
176
|
const ANTHROPIC_DEFAULT_CHAT_URL = "https://api.anthropic.com/v1/messages";
|
|
@@ -210,9 +189,7 @@
|
|
|
210
189
|
mountAccordionSection("#knx-ai-mount-assistant-advanced", "#knx-ai-tab-advanced");
|
|
211
190
|
mountAccordionSection("#knx-ai-mount-chat-adapter", "#knx-ai-tab-chat-adapter");
|
|
212
191
|
mountAccordionSection("#knx-ai-mount-home-intelligence", "#knx-ai-tab-home-intelligence");
|
|
213
|
-
mountAccordionSection("#knx-ai-mount-knx-capture", "#knx-ai-tab-capture");
|
|
214
192
|
mountAccordionSection("#knx-ai-mount-knx-storage", "#knx-ai-tab-storage");
|
|
215
|
-
mountAccordionSection("#knx-ai-mount-knx-detection", "#knx-ai-tab-detection");
|
|
216
193
|
$("#knx-ai-accordion").accordion({
|
|
217
194
|
active: 0,
|
|
218
195
|
animate: false,
|
|
@@ -234,12 +211,6 @@
|
|
|
234
211
|
};
|
|
235
212
|
$("#node-input-historyStoreToDisk").on("change", toggleHistoryArchive);
|
|
236
213
|
|
|
237
|
-
const toggleDocsContext = () => {
|
|
238
|
-
const enabled = $("#node-input-llmIncludeDocsSnippets").is(":checked");
|
|
239
|
-
$("#knx-ai-docs-language-row").toggle(enabled);
|
|
240
|
-
};
|
|
241
|
-
$("#node-input-llmIncludeDocsSnippets").on("change", toggleDocsContext);
|
|
242
|
-
|
|
243
214
|
const toggleCommandConfirmation = () => {
|
|
244
215
|
const enabled = $("#node-input-llmAllowKnxCommands").is(":checked");
|
|
245
216
|
$("#knx-ai-command-confirmation-row").toggle(enabled);
|
|
@@ -248,10 +219,27 @@
|
|
|
248
219
|
|
|
249
220
|
toggleLLM();
|
|
250
221
|
toggleHistoryArchive();
|
|
251
|
-
toggleDocsContext();
|
|
252
222
|
toggleCommandConfirmation();
|
|
253
223
|
|
|
254
|
-
const
|
|
224
|
+
const applyNumericFallback = (selector, fallback) => {
|
|
225
|
+
const $field = $(selector);
|
|
226
|
+
if (!$field.length) return;
|
|
227
|
+
const value = $field.val();
|
|
228
|
+
if (value === undefined || value === null || String(value).trim() === "") {
|
|
229
|
+
$field.val(String(fallback));
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
applyNumericFallback("#node-input-analysisWindowSec", 120);
|
|
233
|
+
applyNumericFallback("#node-input-historyWindowSec", 600);
|
|
234
|
+
applyNumericFallback("#node-input-historyStoreRetentionDays", 10);
|
|
235
|
+
applyNumericFallback("#node-input-emitIntervalSec", 0);
|
|
236
|
+
applyNumericFallback("#node-input-topN", 10);
|
|
237
|
+
applyNumericFallback("#node-input-maxEvents", 50000);
|
|
238
|
+
applyNumericFallback("#node-input-proactiveOpenMinutes", 120);
|
|
239
|
+
applyNumericFallback("#node-input-proactiveCooldownMinutes", 360);
|
|
240
|
+
applyNumericFallback("#node-input-homeMemoryMaxKb", 256);
|
|
241
|
+
|
|
242
|
+
const nodeId = node.id;
|
|
255
243
|
const resolveAdminRoot = () => {
|
|
256
244
|
const raw = (RED.settings && typeof RED.settings.httpAdminRoot === "string") ? RED.settings.httpAdminRoot : "/";
|
|
257
245
|
const trimmed = String(raw || "/").trim();
|
|
@@ -273,12 +261,115 @@
|
|
|
273
261
|
return value;
|
|
274
262
|
};
|
|
275
263
|
|
|
264
|
+
const applyChatEditorOptions = (editor) => {
|
|
265
|
+
try {
|
|
266
|
+
if (!editor) return;
|
|
267
|
+
if (typeof editor.updateOptions === "function") {
|
|
268
|
+
editor.updateOptions({
|
|
269
|
+
lineNumbers: "off",
|
|
270
|
+
minimap: { enabled: false },
|
|
271
|
+
scrollbar: { verticalScrollbarSize: 8, horizontalScrollbarSize: 8 }
|
|
272
|
+
});
|
|
273
|
+
} else if (editor.renderer && typeof editor.renderer.setShowGutter === "function") {
|
|
274
|
+
editor.renderer.setShowGutter(false);
|
|
275
|
+
}
|
|
276
|
+
if (typeof editor.setShowPrintMargin === "function") editor.setShowPrintMargin(false);
|
|
277
|
+
if (typeof editor.setOptions === "function") {
|
|
278
|
+
editor.setOptions({
|
|
279
|
+
enableBasicAutocompletion: true,
|
|
280
|
+
enableLiveAutocompletion: true
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
} catch (error) { }
|
|
284
|
+
};
|
|
285
|
+
const setChatEditorValue = (editor, value) => {
|
|
286
|
+
try {
|
|
287
|
+
if (!editor) return;
|
|
288
|
+
if (typeof editor.setValue === "function") {
|
|
289
|
+
editor.setValue(String(value || ""));
|
|
290
|
+
} else if (editor.session && typeof editor.session.setValue === "function") {
|
|
291
|
+
editor.session.setValue(String(value || ""));
|
|
292
|
+
}
|
|
293
|
+
} catch (error) { }
|
|
294
|
+
};
|
|
295
|
+
const destroyChatEditors = () => {
|
|
296
|
+
["chatInputCodeEditor", "chatOutputCodeEditor"].forEach(function (key) {
|
|
297
|
+
try {
|
|
298
|
+
if (node[key] && typeof node[key].destroy === "function") node[key].destroy();
|
|
299
|
+
} catch (error) { }
|
|
300
|
+
delete node[key];
|
|
301
|
+
});
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
try {
|
|
305
|
+
node.chatInputCodeEditor = RED.editor.createEditor({
|
|
306
|
+
id: "node-input-chatInputCode-editor",
|
|
307
|
+
mode: "ace/mode/nrjavascript",
|
|
308
|
+
value: node.chatInputCode || ""
|
|
309
|
+
});
|
|
310
|
+
} catch (error) { }
|
|
311
|
+
try {
|
|
312
|
+
node.chatOutputCodeEditor = RED.editor.createEditor({
|
|
313
|
+
id: "node-input-chatOutputCode-editor",
|
|
314
|
+
mode: "ace/mode/nrjavascript",
|
|
315
|
+
value: node.chatOutputCode || ""
|
|
316
|
+
});
|
|
317
|
+
} catch (error) { }
|
|
318
|
+
applyChatEditorOptions(node.chatInputCodeEditor);
|
|
319
|
+
applyChatEditorOptions(node.chatOutputCodeEditor);
|
|
320
|
+
if (typeof monaco !== "undefined") {
|
|
321
|
+
try {
|
|
322
|
+
const globalScope = typeof window !== "undefined" ? window : globalThis;
|
|
323
|
+
if (!globalScope._knxAiChatEditorThemesDefined) {
|
|
324
|
+
monaco.editor.defineTheme("knx-ai-chat-input-theme", {
|
|
325
|
+
base: "vs",
|
|
326
|
+
inherit: true,
|
|
327
|
+
rules: [],
|
|
328
|
+
colors: {
|
|
329
|
+
"editor.background": "#e8f5e9",
|
|
330
|
+
"editorGutter.background": "#e8f5e9"
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
monaco.editor.defineTheme("knx-ai-chat-output-theme", {
|
|
334
|
+
base: "vs",
|
|
335
|
+
inherit: true,
|
|
336
|
+
rules: [],
|
|
337
|
+
colors: {
|
|
338
|
+
"editor.background": "#fffde7",
|
|
339
|
+
"editorGutter.background": "#fffde7"
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
globalScope._knxAiChatEditorThemesDefined = true;
|
|
343
|
+
}
|
|
344
|
+
if (node.chatInputCodeEditor && typeof node.chatInputCodeEditor.updateOptions === "function") {
|
|
345
|
+
node.chatInputCodeEditor.updateOptions({ theme: "knx-ai-chat-input-theme" });
|
|
346
|
+
}
|
|
347
|
+
if (node.chatOutputCodeEditor && typeof node.chatOutputCodeEditor.updateOptions === "function") {
|
|
348
|
+
node.chatOutputCodeEditor.updateOptions({ theme: "knx-ai-chat-output-theme" });
|
|
349
|
+
}
|
|
350
|
+
} catch (error) { }
|
|
351
|
+
}
|
|
352
|
+
node._destroyKnxAiChatEditors = destroyChatEditors;
|
|
353
|
+
|
|
276
354
|
const configureChatAdapterPicker = () => {
|
|
277
355
|
const adapters = Array.isArray(window.KNXAIChatAdapterMappings)
|
|
278
356
|
? window.KNXAIChatAdapterMappings.slice()
|
|
279
357
|
: [];
|
|
280
358
|
const $picker = $("#node-input-chatAdapterPreset");
|
|
281
359
|
if (!$picker.length) return;
|
|
360
|
+
const updateAdapterFieldsVisibility = (preset) => {
|
|
361
|
+
const visible = String(preset || "none") !== "none";
|
|
362
|
+
$("#knx-ai-chat-adapter-fields").toggle(visible);
|
|
363
|
+
if (visible) {
|
|
364
|
+
const resizeEditors = function () {
|
|
365
|
+
try {
|
|
366
|
+
if (node.chatInputCodeEditor && typeof node.chatInputCodeEditor.resize === "function") node.chatInputCodeEditor.resize();
|
|
367
|
+
if (node.chatOutputCodeEditor && typeof node.chatOutputCodeEditor.resize === "function") node.chatOutputCodeEditor.resize();
|
|
368
|
+
} catch (error) { }
|
|
369
|
+
};
|
|
370
|
+
try { setTimeout(resizeEditors, 0); } catch (error) { resizeEditors(); }
|
|
371
|
+
}
|
|
372
|
+
};
|
|
282
373
|
$picker.empty();
|
|
283
374
|
$("<option></option>")
|
|
284
375
|
.attr("value", "none")
|
|
@@ -300,20 +391,23 @@
|
|
|
300
391
|
.appendTo($picker);
|
|
301
392
|
}
|
|
302
393
|
$picker.val(configuredPreset);
|
|
394
|
+
updateAdapterFieldsVisibility(configuredPreset);
|
|
303
395
|
$picker.on("change", function () {
|
|
304
396
|
const selected = String($(this).val() || "none");
|
|
305
397
|
if (selected === "none") {
|
|
306
|
-
|
|
307
|
-
|
|
398
|
+
setChatEditorValue(node.chatInputCodeEditor, "");
|
|
399
|
+
setChatEditorValue(node.chatOutputCodeEditor, "");
|
|
400
|
+
updateAdapterFieldsVisibility(selected);
|
|
308
401
|
return;
|
|
309
402
|
}
|
|
310
403
|
const adapter = adapters.find(item => item && item.id === selected);
|
|
311
404
|
if (!adapter) return;
|
|
312
|
-
|
|
313
|
-
|
|
405
|
+
setChatEditorValue(node.chatInputCodeEditor, adapter.inputCode || "");
|
|
406
|
+
setChatEditorValue(node.chatOutputCodeEditor, adapter.outputCode || "");
|
|
407
|
+
updateAdapterFieldsVisibility(selected);
|
|
314
408
|
});
|
|
315
409
|
};
|
|
316
|
-
configureChatAdapterPicker.call(
|
|
410
|
+
configureChatAdapterPicker.call(node);
|
|
317
411
|
|
|
318
412
|
const updateProactiveVisibility = () => {
|
|
319
413
|
const enabled = $("#node-input-proactiveEnabled").is(":checked");
|
|
@@ -335,19 +429,10 @@
|
|
|
335
429
|
try { if (wnd && typeof wnd.focus === "function") wnd.focus(); } catch (e) { }
|
|
336
430
|
});
|
|
337
431
|
|
|
338
|
-
const
|
|
339
|
-
const $
|
|
340
|
-
|
|
341
|
-
$
|
|
342
|
-
$status.removeClass("knx-ai-models-ok knx-ai-models-warn knx-ai-models-err");
|
|
343
|
-
if (level === "ok") $status.addClass("knx-ai-models-ok");
|
|
344
|
-
if (level === "warn") $status.addClass("knx-ai-models-warn");
|
|
345
|
-
if (level === "err") $status.addClass("knx-ai-models-err");
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
const setOllamaNoModelsVisible = (visible) => {
|
|
349
|
-
if (visible) $("#knx-ai-ollama-empty-help").show();
|
|
350
|
-
else $("#knx-ai-ollama-empty-help").hide();
|
|
432
|
+
const setRefreshModelsBusy = (busy) => {
|
|
433
|
+
const $button = $("#knx-ai-refreshModels");
|
|
434
|
+
$button.prop("disabled", !!busy);
|
|
435
|
+
$button.find("i.fa-refresh").toggleClass("fa-spin", !!busy);
|
|
351
436
|
};
|
|
352
437
|
|
|
353
438
|
const setOllamaInstallUiState = (busy) => {
|
|
@@ -399,8 +484,7 @@
|
|
|
399
484
|
// Node-RED uses "__PWRD__" as placeholder for stored credentials: don't send it.
|
|
400
485
|
if (apiKey && apiKey !== "__PWRD__") payload.apiKey = apiKey;
|
|
401
486
|
|
|
402
|
-
|
|
403
|
-
$("#knx-ai-refreshModels").prop("disabled", true);
|
|
487
|
+
setRefreshModelsBusy(true);
|
|
404
488
|
|
|
405
489
|
$.ajax({
|
|
406
490
|
url: "knxUltimateAI/models",
|
|
@@ -410,7 +494,6 @@
|
|
|
410
494
|
})
|
|
411
495
|
.done(function (data) {
|
|
412
496
|
const models = (data && data.models) ? data.models : [];
|
|
413
|
-
let msg = "";
|
|
414
497
|
populateModels(models);
|
|
415
498
|
if (provider === "ollama" && data && data.ollamaStarted) {
|
|
416
499
|
try {
|
|
@@ -419,15 +502,9 @@
|
|
|
419
502
|
} catch (e) { }
|
|
420
503
|
}
|
|
421
504
|
if (provider === "ollama" && models.length === 0) {
|
|
422
|
-
msg = t('knxUltimateAI.messages.ollamaNoModels', "No local Ollama model found. Install one from https://ollama.com/library.");
|
|
423
|
-
|
|
424
|
-
setOllamaNoModelsVisible(true);
|
|
425
|
-
} else {
|
|
426
|
-
msg = t('knxUltimateAI.messages.loadedModels', "Models loaded") + ": " + models.length;
|
|
427
|
-
setModelsStatus(msg, "ok");
|
|
428
|
-
setOllamaNoModelsVisible(false);
|
|
505
|
+
const msg = t('knxUltimateAI.messages.ollamaNoModels', "No local Ollama model found. Install one from https://ollama.com/library.");
|
|
506
|
+
try { RED.notify(msg, "warning"); } catch (e) { }
|
|
429
507
|
}
|
|
430
|
-
try { RED.notify(msg, "success"); } catch (e) { }
|
|
431
508
|
})
|
|
432
509
|
.fail(function (xhr) {
|
|
433
510
|
let err = "Failed to load models";
|
|
@@ -435,11 +512,10 @@
|
|
|
435
512
|
const resp = xhr && xhr.responseJSON;
|
|
436
513
|
if (resp && resp.error) err = resp.error;
|
|
437
514
|
} catch (e) { }
|
|
438
|
-
setModelsStatus(err, "err");
|
|
439
515
|
try { RED.notify(err, "error"); } catch (e) { }
|
|
440
516
|
})
|
|
441
517
|
.always(function () {
|
|
442
|
-
|
|
518
|
+
setRefreshModelsBusy(false);
|
|
443
519
|
});
|
|
444
520
|
};
|
|
445
521
|
|
|
@@ -450,7 +526,6 @@
|
|
|
450
526
|
const model = String($("#node-input-llmModel").val() || "").trim() || OLLAMA_DEFAULT_MODEL;
|
|
451
527
|
const payload = { nodeId: nodeId, baseUrl: baseUrl, model: model };
|
|
452
528
|
|
|
453
|
-
setModelsStatus(t('knxUltimateAI.messages.installingOllamaModel', "Installing Ollama model..."), "warn");
|
|
454
529
|
$("#knx-ai-refreshModels").prop("disabled", true);
|
|
455
530
|
setOllamaInstallUiState(true);
|
|
456
531
|
|
|
@@ -477,11 +552,10 @@
|
|
|
477
552
|
const resp = xhr && xhr.responseJSON;
|
|
478
553
|
if (resp && resp.error) err = resp.error;
|
|
479
554
|
} catch (e) { }
|
|
480
|
-
setModelsStatus(err, "err");
|
|
481
555
|
try { RED.notify(err, "error"); } catch (e) { }
|
|
556
|
+
$("#knx-ai-refreshModels").prop("disabled", false);
|
|
482
557
|
})
|
|
483
558
|
.always(function () {
|
|
484
|
-
$("#knx-ai-refreshModels").prop("disabled", false);
|
|
485
559
|
setOllamaInstallUiState(false);
|
|
486
560
|
});
|
|
487
561
|
};
|
|
@@ -496,16 +570,11 @@
|
|
|
496
570
|
if (applyDefaults) applyProviderDefaults(provider);
|
|
497
571
|
if (provider === "ollama") {
|
|
498
572
|
$("#knx-ai-apikey-row").hide();
|
|
499
|
-
$("#knx-ai-ollama-warning").show();
|
|
500
573
|
$("#knx-ai-ollama-install-row").show();
|
|
501
|
-
$("#knx-ai-ollama-steps").show();
|
|
502
574
|
if (autoLoadModels) refreshModels();
|
|
503
575
|
} else {
|
|
504
576
|
$("#knx-ai-apikey-row").show();
|
|
505
|
-
$("#knx-ai-ollama-warning").hide();
|
|
506
577
|
$("#knx-ai-ollama-install-row").hide();
|
|
507
|
-
$("#knx-ai-ollama-steps").hide();
|
|
508
|
-
setOllamaNoModelsVisible(false);
|
|
509
578
|
}
|
|
510
579
|
};
|
|
511
580
|
$("#node-input-llmProvider").on("change", function () {
|
|
@@ -528,9 +597,35 @@
|
|
|
528
597
|
},
|
|
529
598
|
oneditsave: function () {
|
|
530
599
|
try { RED.sidebar.show("info"); } catch (error) { }
|
|
600
|
+
try {
|
|
601
|
+
if (this.chatInputCodeEditor && typeof this.chatInputCodeEditor.getValue === "function") {
|
|
602
|
+
this.chatInputCode = this.chatInputCodeEditor.getValue();
|
|
603
|
+
$("#node-input-chatInputCode").val(this.chatInputCode);
|
|
604
|
+
}
|
|
605
|
+
} catch (error) { }
|
|
606
|
+
try {
|
|
607
|
+
if (this.chatOutputCodeEditor && typeof this.chatOutputCodeEditor.getValue === "function") {
|
|
608
|
+
this.chatOutputCode = this.chatOutputCodeEditor.getValue();
|
|
609
|
+
$("#node-input-chatOutputCode").val(this.chatOutputCode);
|
|
610
|
+
}
|
|
611
|
+
} catch (error) { }
|
|
612
|
+
try {
|
|
613
|
+
if (typeof this._destroyKnxAiChatEditors === "function") this._destroyKnxAiChatEditors();
|
|
614
|
+
} catch (error) { }
|
|
615
|
+
delete this._destroyKnxAiChatEditors;
|
|
531
616
|
},
|
|
532
617
|
oneditcancel: function () {
|
|
533
618
|
try { RED.sidebar.show("info"); } catch (error) { }
|
|
619
|
+
try {
|
|
620
|
+
if (typeof this._destroyKnxAiChatEditors === "function") this._destroyKnxAiChatEditors();
|
|
621
|
+
} catch (error) { }
|
|
622
|
+
delete this._destroyKnxAiChatEditors;
|
|
623
|
+
},
|
|
624
|
+
oneditresize: function () {
|
|
625
|
+
try {
|
|
626
|
+
if (this.chatInputCodeEditor && typeof this.chatInputCodeEditor.resize === "function") this.chatInputCodeEditor.resize();
|
|
627
|
+
if (this.chatOutputCodeEditor && typeof this.chatOutputCodeEditor.resize === "function") this.chatOutputCodeEditor.resize();
|
|
628
|
+
} catch (error) { }
|
|
534
629
|
}
|
|
535
630
|
})
|
|
536
631
|
</script>
|
|
@@ -597,38 +692,15 @@
|
|
|
597
692
|
|
|
598
693
|
<h3><i class="fa fa-exchange"></i> <span data-i18n="knxUltimateAI.sections.groupKnxAnalysis"></span></h3>
|
|
599
694
|
<div>
|
|
600
|
-
<div class="knx-ai-accordion-subsection">
|
|
601
|
-
<h4><i class="fa fa-sign-in"></i> <span data-i18n="knxUltimateAI.sections.capture"></span></h4>
|
|
602
|
-
<div class="knx-ai-accordion-mount" id="knx-ai-mount-knx-capture"></div>
|
|
603
|
-
</div>
|
|
604
695
|
<div class="knx-ai-accordion-subsection">
|
|
605
696
|
<h4><i class="fa fa-database"></i> <span data-i18n="knxUltimateAI.sections.storage"></span></h4>
|
|
606
697
|
<div class="knx-ai-accordion-mount" id="knx-ai-mount-knx-storage"></div>
|
|
607
698
|
</div>
|
|
608
|
-
<div class="knx-ai-accordion-subsection">
|
|
609
|
-
<h4><i class="fa fa-search"></i> <span data-i18n="knxUltimateAI.sections.detection"></span></h4>
|
|
610
|
-
<div class="knx-ai-accordion-mount" id="knx-ai-mount-knx-detection"></div>
|
|
611
|
-
</div>
|
|
612
699
|
</div>
|
|
613
700
|
</div>
|
|
614
701
|
|
|
615
702
|
<div id="knx-ai-accordion-source" style="display:none;">
|
|
616
703
|
|
|
617
|
-
<div id="knx-ai-tab-capture">
|
|
618
|
-
<div class="form-row">
|
|
619
|
-
<input type="checkbox" id="node-input-notifywrite" style="display:inline-block; width:auto; vertical-align:top;">
|
|
620
|
-
<label style="width:auto" for="node-input-notifywrite"> <span data-i18n="knxUltimateAI.properties.notifywrite"></span></label>
|
|
621
|
-
</div>
|
|
622
|
-
<div class="form-row">
|
|
623
|
-
<input type="checkbox" id="node-input-notifyresponse" style="display:inline-block; width:auto; vertical-align:top;">
|
|
624
|
-
<label style="width:auto" for="node-input-notifyresponse"> <span data-i18n="knxUltimateAI.properties.notifyresponse"></span></label>
|
|
625
|
-
</div>
|
|
626
|
-
<div class="form-row">
|
|
627
|
-
<input type="checkbox" id="node-input-notifyreadrequest" style="display:inline-block; width:auto; vertical-align:top;">
|
|
628
|
-
<label style="width:auto" for="node-input-notifyreadrequest"> <span data-i18n="knxUltimateAI.properties.notifyreadrequest"></span></label>
|
|
629
|
-
</div>
|
|
630
|
-
</div>
|
|
631
|
-
|
|
632
704
|
<div id="knx-ai-tab-storage">
|
|
633
705
|
<div class="form-row">
|
|
634
706
|
<label style="width:290px" for="node-input-historyWindowSec"><i class="fa fa-history"></i> <span data-i18n="knxUltimateAI.properties.historyWindowSec"></span></label>
|
|
@@ -660,41 +732,6 @@
|
|
|
660
732
|
</div>
|
|
661
733
|
</div>
|
|
662
734
|
|
|
663
|
-
<div id="knx-ai-tab-detection">
|
|
664
|
-
<div class="form-row">
|
|
665
|
-
<input type="checkbox" id="node-input-enablePattern" style="display:inline-block; width:auto; vertical-align:top;">
|
|
666
|
-
<label style="width:auto" for="node-input-enablePattern"> <span data-i18n="knxUltimateAI.properties.enablePattern"></span></label>
|
|
667
|
-
</div>
|
|
668
|
-
<div class="form-row">
|
|
669
|
-
<label style="width:290px" for="node-input-patternMaxLagMs"><i class="fa fa-arrows-h"></i> <span data-i18n="knxUltimateAI.properties.patternMaxLagMs"></span></label>
|
|
670
|
-
<input style="width:120px" type="number" id="node-input-patternMaxLagMs">
|
|
671
|
-
</div>
|
|
672
|
-
<div class="form-row">
|
|
673
|
-
<label style="width:290px" for="node-input-patternMinCount"><i class="fa fa-filter"></i> <span data-i18n="knxUltimateAI.properties.patternMinCount"></span></label>
|
|
674
|
-
<input style="width:90px" type="number" id="node-input-patternMinCount">
|
|
675
|
-
</div>
|
|
676
|
-
<div class="form-row">
|
|
677
|
-
<label style="width:290px" for="node-input-rateWindowSec"><i class="fa fa-clock-o"></i> <span data-i18n="knxUltimateAI.properties.rateWindowSec"></span></label>
|
|
678
|
-
<input style="width:90px" type="number" id="node-input-rateWindowSec">
|
|
679
|
-
</div>
|
|
680
|
-
<div class="form-row">
|
|
681
|
-
<label style="width:290px" for="node-input-maxTelegramPerSecOverall"><i class="fa fa-tachometer"></i> <span data-i18n="knxUltimateAI.properties.maxTelegramPerSecOverall"></span></label>
|
|
682
|
-
<input style="width:90px" type="number" id="node-input-maxTelegramPerSecOverall">
|
|
683
|
-
</div>
|
|
684
|
-
<div class="form-row">
|
|
685
|
-
<label style="width:290px" for="node-input-maxTelegramPerSecPerGA"><i class="fa fa-bolt"></i> <span data-i18n="knxUltimateAI.properties.maxTelegramPerSecPerGA"></span></label>
|
|
686
|
-
<input style="width:90px" type="number" id="node-input-maxTelegramPerSecPerGA">
|
|
687
|
-
</div>
|
|
688
|
-
<div class="form-row">
|
|
689
|
-
<label style="width:290px" for="node-input-flapWindowSec"><i class="fa fa-exchange"></i> <span data-i18n="knxUltimateAI.properties.flapWindowSec"></span></label>
|
|
690
|
-
<input style="width:90px" type="number" id="node-input-flapWindowSec">
|
|
691
|
-
</div>
|
|
692
|
-
<div class="form-row">
|
|
693
|
-
<label style="width:290px" for="node-input-flapMaxChanges"><i class="fa fa-random"></i> <span data-i18n="knxUltimateAI.properties.flapMaxChanges"></span></label>
|
|
694
|
-
<input style="width:90px" type="number" id="node-input-flapMaxChanges">
|
|
695
|
-
</div>
|
|
696
|
-
</div>
|
|
697
|
-
|
|
698
735
|
<div id="knx-ai-tab-llm-connection">
|
|
699
736
|
<div class="form-row">
|
|
700
737
|
<input type="checkbox" id="node-input-llmEnabled" style="display:inline-block; width:auto; vertical-align:top;">
|
|
@@ -723,7 +760,6 @@
|
|
|
723
760
|
</button>
|
|
724
761
|
</div>
|
|
725
762
|
<datalist id="knx-ai-llmModels"></datalist>
|
|
726
|
-
<div class="form-tips" id="knx-ai-models-status"></div>
|
|
727
763
|
<div class="form-row">
|
|
728
764
|
<input type="checkbox" id="node-input-llmAllowKnxCommands" style="display:inline-block; width:auto; vertical-align:top;">
|
|
729
765
|
<label style="width:auto" for="node-input-llmAllowKnxCommands"> <span data-i18n="knxUltimateAI.properties.llmAllowKnxCommands"></span></label>
|
|
@@ -736,32 +772,27 @@
|
|
|
736
772
|
</div>
|
|
737
773
|
|
|
738
774
|
<div id="knx-ai-tab-chat-adapter">
|
|
739
|
-
<div class="form-tips" style="margin-bottom:12px;">
|
|
740
|
-
<span data-i18n="knxUltimateAI.messages.chatAdapterIntro"></span>
|
|
741
|
-
</div>
|
|
742
775
|
<div class="form-row">
|
|
743
776
|
<label style="width:290px" for="node-input-chatAdapterPreset"><i class="fa fa-plug"></i> <span data-i18n="knxUltimateAI.properties.chatAdapterPreset"></span></label>
|
|
744
777
|
<select style="width:100%" id="node-input-chatAdapterPreset">
|
|
745
778
|
<option value="none" data-i18n="knxUltimateAI.selectlists.chatAdapter.none"></option>
|
|
746
779
|
</select>
|
|
747
780
|
</div>
|
|
748
|
-
<div
|
|
749
|
-
<
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
<
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
781
|
+
<div id="knx-ai-chat-adapter-fields" style="display:none;">
|
|
782
|
+
<div class="form-row">
|
|
783
|
+
<label style="width:100%" for="node-input-chatInputCode"><i class="fa fa-sign-in"></i> <span data-i18n="knxUltimateAI.properties.chatInputCode"></span></label>
|
|
784
|
+
<input type="hidden" id="node-input-chatInputCode">
|
|
785
|
+
<div id="node-input-chatInputCode-editor" class="node-text-editor knx-ai-chat-adapter-editor"></div>
|
|
786
|
+
</div>
|
|
787
|
+
<div class="form-row">
|
|
788
|
+
<label style="width:100%" for="node-input-chatOutputCode"><i class="fa fa-sign-out"></i> <span data-i18n="knxUltimateAI.properties.chatOutputCode"></span></label>
|
|
789
|
+
<input type="hidden" id="node-input-chatOutputCode">
|
|
790
|
+
<div id="node-input-chatOutputCode-editor" class="node-text-editor knx-ai-chat-adapter-editor"></div>
|
|
791
|
+
</div>
|
|
758
792
|
</div>
|
|
759
793
|
</div>
|
|
760
794
|
|
|
761
795
|
<div id="knx-ai-tab-home-intelligence">
|
|
762
|
-
<div class="form-tips" style="margin-bottom:12px;">
|
|
763
|
-
<span data-i18n="knxUltimateAI.messages.homeIntelligenceIntro"></span>
|
|
764
|
-
</div>
|
|
765
796
|
<div class="form-row">
|
|
766
797
|
<input type="checkbox" id="node-input-proactiveEnabled" style="display:inline-block; width:auto; vertical-align:top;">
|
|
767
798
|
<label style="width:auto" for="node-input-proactiveEnabled"> <span data-i18n="knxUltimateAI.properties.proactiveEnabled"></span></label>
|
|
@@ -788,9 +819,6 @@
|
|
|
788
819
|
<label style="width:100%" for="node-input-aiEducation"><i class="fa fa-graduation-cap"></i> <span data-i18n="knxUltimateAI.properties.aiEducation"></span></label>
|
|
789
820
|
<textarea id="node-input-aiEducation" maxlength="16000" style="width:100%; min-height:180px; box-sizing:border-box;" data-i18n="[placeholder]knxUltimateAI.placeholder.aiEducation"></textarea>
|
|
790
821
|
</div>
|
|
791
|
-
<div class="form-tips" style="margin-bottom:12px;">
|
|
792
|
-
<span data-i18n="knxUltimateAI.messages.aiEducationHelp"></span>
|
|
793
|
-
</div>
|
|
794
822
|
<div class="knx-ai-inline-subsection">
|
|
795
823
|
<h5><i class="fa fa-sliders"></i> <span data-i18n="knxUltimateAI.sections.homeIntelligenceAdvanced"></span></h5>
|
|
796
824
|
<div>
|
|
@@ -802,30 +830,17 @@
|
|
|
802
830
|
<label style="width:290px" for="node-input-homeMemoryMaxKb"><i class="fa fa-hdd-o"></i> <span data-i18n="knxUltimateAI.properties.homeMemoryMaxKb"></span></label>
|
|
803
831
|
<input style="width:100px" type="number" min="64" max="1024" id="node-input-homeMemoryMaxKb">
|
|
804
832
|
</div>
|
|
805
|
-
<div class="form-tips">
|
|
806
|
-
<span data-i18n="knxUltimateAI.messages.homeMemoryLimitHelp"></span>
|
|
807
|
-
</div>
|
|
808
833
|
</div>
|
|
809
834
|
</div>
|
|
810
835
|
</div>
|
|
811
836
|
|
|
812
837
|
<div id="knx-ai-tab-llm-context">
|
|
813
838
|
<div id="knx-ai-llm-context-settings">
|
|
814
|
-
<div class="form-row">
|
|
815
|
-
<input type="checkbox" id="node-input-llmIncludeRaw" style="display:inline-block; width:auto; vertical-align:top;">
|
|
816
|
-
<label style="width:auto" for="node-input-llmIncludeRaw"> <span data-i18n="knxUltimateAI.properties.llmIncludeRaw"></span></label>
|
|
817
|
-
</div>
|
|
818
|
-
|
|
819
839
|
<div class="form-row">
|
|
820
840
|
<input type="checkbox" id="node-input-llmIncludeFlowContext" style="display:inline-block; width:auto; vertical-align:top;">
|
|
821
841
|
<label style="width:auto" for="node-input-llmIncludeFlowContext"> <span data-i18n="knxUltimateAI.properties.llmIncludeFlowContext"></span></label>
|
|
822
842
|
</div>
|
|
823
843
|
|
|
824
|
-
<div class="form-row">
|
|
825
|
-
<input type="checkbox" id="node-input-llmIncludeDocsSnippets" style="display:inline-block; width:auto; vertical-align:top;">
|
|
826
|
-
<label style="width:auto" for="node-input-llmIncludeDocsSnippets"> <span data-i18n="knxUltimateAI.properties.llmIncludeDocsSnippets"></span></label>
|
|
827
|
-
</div>
|
|
828
|
-
|
|
829
844
|
<div class="form-row" id="knx-ai-docs-language-row">
|
|
830
845
|
<label style="width:290px" for="node-input-llmDocsLanguage"><i class="fa fa-language"></i> <span data-i18n="knxUltimateAI.properties.llmDocsLanguage"></span></label>
|
|
831
846
|
<select style="width:100%" id="node-input-llmDocsLanguage">
|
|
@@ -837,10 +852,6 @@
|
|
|
837
852
|
<option value="zh-CN">简体中文</option>
|
|
838
853
|
</select>
|
|
839
854
|
</div>
|
|
840
|
-
<div class="form-row">
|
|
841
|
-
<label style="width:290px" for="node-input-llmSystemPrompt"><i class="fa fa-commenting-o"></i> <span data-i18n="knxUltimateAI.properties.llmSystemPrompt"></span></label>
|
|
842
|
-
<textarea style="width:100%; height:110px;" id="node-input-llmSystemPrompt" data-i18n="[placeholder]knxUltimateAI.placeholder.llmSystemPrompt"></textarea>
|
|
843
|
-
</div>
|
|
844
855
|
</div>
|
|
845
856
|
</div>
|
|
846
857
|
|
|
@@ -850,9 +861,6 @@
|
|
|
850
861
|
<label style="width:290px" for="node-input-llmBaseUrl"><i class="fa fa-link"></i> <span data-i18n="knxUltimateAI.properties.llmBaseUrl"></span></label>
|
|
851
862
|
<input type="text" id="node-input-llmBaseUrl" data-i18n="[placeholder]knxUltimateAI.placeholder.llmBaseUrl">
|
|
852
863
|
</div>
|
|
853
|
-
<div class="form-tips" id="knx-ai-ollama-warning" style="display:none;">
|
|
854
|
-
<span data-i18n="knxUltimateAI.messages.ollamaNotSupported"></span>
|
|
855
|
-
</div>
|
|
856
864
|
<div class="form-row" id="knx-ai-ollama-install-row" style="display:none;">
|
|
857
865
|
<label style="width:290px"><i class="fa fa-download"></i> Ollama</label>
|
|
858
866
|
<div class="knx-ai-ollama-actions">
|
|
@@ -864,14 +872,6 @@
|
|
|
864
872
|
</button>
|
|
865
873
|
</div>
|
|
866
874
|
</div>
|
|
867
|
-
<div class="form-tips" id="knx-ai-ollama-steps" style="display:none;">
|
|
868
|
-
<span data-i18n="knxUltimateAI.messages.ollamaInstallSteps"></span>
|
|
869
|
-
</div>
|
|
870
|
-
<div class="form-tips" id="knx-ai-ollama-empty-help" style="display:none;">
|
|
871
|
-
<span data-i18n="knxUltimateAI.messages.ollamaNoModels"></span>
|
|
872
|
-
<br>
|
|
873
|
-
<code>ollama pull llama3.1</code>
|
|
874
|
-
</div>
|
|
875
875
|
</div>
|
|
876
876
|
</div>
|
|
877
877
|
</div>
|