iobroker.javascript 10.3.0 → 10.4.1
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/README.md +23 -22
- package/admin/assets/AiChatPanel-CfjSsVpE.js +27 -0
- package/admin/assets/AiChatService-rFZwYNPk.js +216 -0
- package/admin/assets/AiDiffView-DeynDw7L.js +1 -0
- package/admin/assets/AiInlineProvider-R_AVYwFT.js +5 -0
- package/admin/assets/{BlocklyEditor-BZyoN1JE.js → BlocklyEditor-DPJkoxjP.js} +7 -7
- package/admin/assets/Compile-BgTrxmPA.js +165 -0
- package/admin/assets/Debugger-CThCzBvP.js +15 -0
- package/admin/assets/Diff--plofAtP.js +1 -0
- package/admin/assets/{Documentation-uz4Ut9pT.js → Documentation-D3E0U4AK.js} +4 -4
- package/admin/assets/ExpandMore-Dio4GeHC.js +1 -0
- package/admin/assets/{FbEditor-aOZ-RpPV.js → FbEditor-A7I5U0hA.js} +6 -6
- package/admin/assets/History-Ewi5YEEn.js +1 -0
- package/admin/assets/Import-6Mm2vrM2.js +1 -0
- package/admin/assets/MonacoDiff-BYvG7IqB.js +1 -0
- package/admin/assets/{NotificationsActive-BdzH44gp.js → NotificationsActive-CuNfWVJM.js} +1 -1
- package/admin/assets/RulesEditor-MDkGXERp.js +1 -0
- package/admin/assets/{ScriptEditor-CviB6Hif.js → ScriptEditor-CqphehA8.js} +2 -2
- package/admin/assets/ScriptEditorVanillaMonaco-CxgNa-3O.js +3 -0
- package/admin/assets/Send-Pz1eveU5.js +1 -0
- package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-Ceh8EDcF.js +1 -0
- package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__234968779812303__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BRdHvuuG.js +1217 -0
- package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__234968779812303__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DLWT3PGo.js +9 -0
- package/admin/assets/aiPromptBuilder-CI2ChET0.js +1 -0
- package/admin/assets/{blockly-fcfyKYzp.js → blockly-B0t_IRJQ.js} +1 -1
- package/admin/assets/{blocklyTheme-CGhU3cEO.js → blocklyTheme-iZoge1S9.js} +1 -1
- package/admin/assets/{blocks_action-BQ4O7NRE.js → blocks_action-3CepYoiX.js} +1 -1
- package/admin/assets/{blocks_convert-0VBjfhqQ.js → blocks_convert-BEpxVx-_.js} +1 -1
- package/admin/assets/{blocks_logic-DAo99xDr.js → blocks_logic-CyIBT53p.js} +1 -1
- package/admin/assets/{blocks_number-C--e19NU.js → blocks_number-yqm4qwfh.js} +1 -1
- package/admin/assets/{blocks_object-D0TPhdzg.js → blocks_object-CizLkmWp.js} +1 -1
- package/admin/assets/blocks_procedures-pFTThYqz.js +3 -0
- package/admin/assets/{blocks_sendto-CRIrtOUc.js → blocks_sendto-rEq1xPmO.js} +2 -2
- package/admin/assets/{blocks_switch-b_GYfF0n.js → blocks_switch-D3aybjqu.js} +1 -1
- package/admin/assets/{blocks_system-BdkUdSsc.js → blocks_system-BVRsS2OE.js} +1 -1
- package/admin/assets/{blocks_text-DSFhEVOf.js → blocks_text-D93xQ_03.js} +1 -1
- package/admin/assets/{blocks_time-CqALAiJp.js → blocks_time-ChxhjgD7.js} +1 -1
- package/admin/assets/{blocks_timeout-yrOD2pZp.js → blocks_timeout-CUZ80HaP.js} +1 -1
- package/admin/assets/{blocks_trigger-DeAYXpSS.js → blocks_trigger-DivLpAuy.js} +2 -2
- package/admin/assets/{cronHoverProvider-DoO2_tpG.js → cronHoverProvider-Curcjz4m.js} +1 -1
- package/admin/assets/dist-CzitsFi7.js +1 -0
- package/admin/assets/field_cron-RgLY53_S.js +1 -0
- package/admin/assets/field_oid-rBhotXJe.js +1 -0
- package/admin/assets/field_script-CU7g3-oB.js +1 -0
- package/admin/assets/helpers-BZgjFQNf.js +1 -0
- package/admin/assets/{helpers-BTGaTdnT.js → helpers-Bt4VKZBw.js} +1 -1
- package/admin/assets/hostInit-CrHjJGJJ.js +1 -0
- package/admin/assets/index-DzAQnPTD.js +157 -0
- package/admin/assets/{inlineChatWidget-BwQVCPkx.js → inlineChatWidget-ChchJD9a.js} +1 -1
- package/admin/assets/{inlineDiffController-BsDDsDHn.js → inlineDiffController-ly6qX4jk.js} +1 -1
- package/admin/assets/{loadBlocks-RpqM7PwO.js → loadBlocks-DDLPEDa6.js} +23 -23
- package/admin/assets/{mf-entry-bootstrap-0-0deef484.js → mf-entry-bootstrap-0-d055f05d.js} +3 -3
- package/admin/assets/pendingShares-mBGPbRwZ.js +2 -0
- package/admin/assets/{reactour.esm-DX9ZgYlx.js → reactour.esm-Dk3aGxKn.js} +5 -5
- package/admin/assets/{stateHoverProvider-BEadnSXp.js → stateHoverProvider-wAsP-THx.js} +1 -1
- package/admin/assets/utils-DUKzLJUz.js +4 -0
- package/admin/assets/vite-preload-helper-DjNwdemH.js +1 -0
- package/admin/custom/assets/Components-fDcxCyN4.js +1 -0
- package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-BraOrMSu.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-DbKT6Hsb.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-CVvbIPAy.js +1 -0
- package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DVb0ZZ1Q.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BhZYie9-.js} +89 -89
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.js-CV50dgj4.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__date_mf_2_fns__loadShare__.js-Djg9OMcQ.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__leaflet__loadShare__.js-D9EyCd42.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__shared-Hb6V6BnJ.js +2 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-BrY-nF2a.js +122 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild__leaflet__prebuild__-CHjWtrkp.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild__react_mf_2_dom_mf_1_client__prebuild__-DOkC-g0X.js +9 -0
- package/admin/custom/assets/dist-CzitsFi7.js +1 -0
- package/admin/custom/assets/helpers-BZgjFQNf.js +1 -0
- package/admin/custom/assets/hostInit-akwaQLq8.js +1 -0
- package/admin/custom/assets/index-BkItz-nL.js +1 -0
- package/admin/custom/assets/{lib-BmDlTzq2.js → lib-CADOx2YN.js} +1 -1
- package/admin/custom/assets/{mf-entry-bootstrap-0-ad1cd7d0.js → mf-entry-bootstrap-0-3c4565e0.js} +3 -3
- package/admin/custom/assets/pendingShares-TCMDgBLn.js +2 -0
- package/admin/custom/assets/utils-DUKzLJUz.js +4 -0
- package/admin/custom/assets/vite-preload-helper-DjNwdemH.js +1 -0
- package/admin/custom/customComponents.js +2 -2
- package/admin/custom/i18n/de.json +19 -1
- package/admin/custom/i18n/en.json +19 -1
- package/admin/custom/i18n/es.json +19 -1
- package/admin/custom/i18n/fr.json +19 -1
- package/admin/custom/i18n/it.json +19 -1
- package/admin/custom/i18n/nl.json +19 -1
- package/admin/custom/i18n/pl.json +19 -1
- package/admin/custom/i18n/pt.json +19 -1
- package/admin/custom/i18n/ru.json +19 -1
- package/admin/custom/i18n/uk.json +19 -1
- package/admin/custom/i18n/zh-cn.json +19 -1
- package/admin/i18n/de.json +13 -1
- package/admin/i18n/en.json +13 -1
- package/admin/i18n/es.json +13 -1
- package/admin/i18n/fr.json +13 -1
- package/admin/i18n/it.json +13 -1
- package/admin/i18n/nl.json +13 -1
- package/admin/i18n/pl.json +13 -1
- package/admin/i18n/pt.json +13 -1
- package/admin/i18n/ru.json +13 -1
- package/admin/i18n/uk.json +13 -1
- package/admin/i18n/zh-cn.json +13 -1
- package/admin/jsonConfig.json +274 -86
- package/admin/mf-manifest.json +1 -1
- package/admin/mf-stats.json +1 -1
- package/admin/remoteEntry.js +2 -2
- package/admin/tab.html +2 -2
- package/build/lib/ai.js +53 -0
- package/build/lib/ai.js.map +1 -0
- package/build/lib/inspect.js +66 -10
- package/build/lib/inspect.js.map +1 -1
- package/build/lib/mirror.js +24 -23
- package/build/lib/mirror.js.map +1 -1
- package/build/lib/scriptHistory.js +245 -0
- package/build/lib/scriptHistory.js.map +1 -0
- package/build/main.js +358 -413
- package/build/main.js.map +1 -1
- package/build/types.d.ts +11 -0
- package/io-package.json +17 -15
- package/package.json +8 -7
- package/admin/assets/AiChatPanel-CpY4Bun-.js +0 -27
- package/admin/assets/AiChatService-QKcpW4jQ.js +0 -216
- package/admin/assets/AiDiffView-DscPfZ38.js +0 -1
- package/admin/assets/AiInlineProvider-DTSPKoXG.js +0 -5
- package/admin/assets/Compile-Oss28m_f.js +0 -165
- package/admin/assets/Debugger-teJTIU-2.js +0 -15
- package/admin/assets/ExpandMore-V5Ix1QB1.js +0 -1
- package/admin/assets/Import-BIC5Ee9z.js +0 -1
- package/admin/assets/RulesEditor-CcDVthPa.js +0 -1
- package/admin/assets/ScriptEditorVanillaMonaco-ByuXwybM.js +0 -3
- package/admin/assets/Send-Mdo32jMb.js +0 -1
- package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-BnL93BgK.js +0 -1
- package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-NI-3Uv4e.js +0 -1217
- package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DVaMIZyC.js +0 -9
- package/admin/assets/aiPromptBuilder-yTB6N2VT.js +0 -1
- package/admin/assets/blocks_procedures-DgTxgXdB.js +0 -3
- package/admin/assets/dist-D4uJqRBO.js +0 -4
- package/admin/assets/field_cron-D3Ts_s9M.js +0 -1
- package/admin/assets/field_oid-BRNXredg.js +0 -1
- package/admin/assets/field_script-3X6ousg7.js +0 -1
- package/admin/assets/hostInit-2h2Cbsaw.js +0 -1
- package/admin/assets/index-CbQlIKB_.js +0 -156
- package/admin/assets/pendingShares-BaAadIDv.js +0 -1
- package/admin/assets/vite-preload-helper-CaC3yEL3.js +0 -1
- package/admin/custom/assets/Components-FkGDIlId.js +0 -1
- package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-Cs88NUCd.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-P-8ffWXw.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-ZVuRAEo5.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-Dna3WF04.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.js-DcjdCGAx.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__date_mf_2_fns__loadShare__.js-CnhNjamd.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__leaflet__loadShare__.js-Dz7BFJqH.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-B0olko2J.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-CzN4reh_.js +0 -122
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__leaflet__prebuild__-xPcBaiTQ.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__react_mf_2_dom_mf_1_client__prebuild__-DuFBE5fh.js +0 -9
- package/admin/custom/assets/dist-D4uJqRBO.js +0 -4
- package/admin/custom/assets/hostInit-6oh4UY2k.js +0 -1
- package/admin/custom/assets/index-BrlyEy6J.js +0 -1
- package/admin/custom/assets/pendingShares-kV2kwejX.js +0 -1
- package/admin/custom/assets/vite-preload-helper-CaC3yEL3.js +0 -1
- package/build/lib/aiProviderResolver.js +0 -140
- package/build/lib/aiProviderResolver.js.map +0 -1
- package/build/lib/anthropicAdapter.js +0 -175
- package/build/lib/anthropicAdapter.js.map +0 -1
- /package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-CXpyx8Vy.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-CXpyx8Vy.js} +0 -0
package/build/types.d.ts
CHANGED
|
@@ -55,6 +55,17 @@ export interface JavaScriptAdapterConfig {
|
|
|
55
55
|
* at all and the endpoint decides - which is what a reasoning model behind a proxy wants.
|
|
56
56
|
*/
|
|
57
57
|
aiReasoningEffort?: '' | 'none' | 'minimal' | 'low' | 'medium' | 'high';
|
|
58
|
+
/**
|
|
59
|
+
* Upper bound for the answer of an Anthropic model, in tokens. Anthropic requires the field, so
|
|
60
|
+
* unlike the other providers it cannot be left to the endpoint. 8192 fits every model Anthropic
|
|
61
|
+
* currently offers; the newer ones go far beyond that, which is why this is a setting.
|
|
62
|
+
*/
|
|
63
|
+
aiMaxTokens?: number;
|
|
64
|
+
/**
|
|
65
|
+
* How many saved versions of a script to keep in the file area of the instance.
|
|
66
|
+
* `0` switches the history off.
|
|
67
|
+
*/
|
|
68
|
+
historyVersions?: number;
|
|
58
69
|
claudeKey: string;
|
|
59
70
|
geminiKey: string;
|
|
60
71
|
deepseekKey: string;
|
package/io-package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "javascript",
|
|
4
|
-
"version": "10.
|
|
4
|
+
"version": "10.4.1",
|
|
5
5
|
"blockedVersions": [
|
|
6
6
|
"8.0.0",
|
|
7
7
|
"8.0.1"
|
|
@@ -40,6 +40,19 @@
|
|
|
40
40
|
"Matthias Kleine <info@haus-automatisierung.com>"
|
|
41
41
|
],
|
|
42
42
|
"news": {
|
|
43
|
+
"10.4.1": {
|
|
44
|
+
"en": "Changed: the AI assistant uses the shared libraries `@iobroker/ai-core` and `@iobroker/ai-gui`",
|
|
45
|
+
"de": "Geändert: Der KI-Assistent nutzt die Bibliotheken @iobroker /ai-core und @iobroker /ai-gui",
|
|
46
|
+
"ru": "Изменено: помощник по искусственному интеллекту использует разделяемые библиотеки `@iobroker /ai-core` и `@iobroker /ai-gui`",
|
|
47
|
+
"pt": "Alterado: o assistente de IA usa as bibliotecas `@iobroker /ai-core` e `@iobroker /ai-gui`",
|
|
48
|
+
"nl": "Gewijzigd: de AI-assistent gebruikt de gedeelde bibliotheken `@iobroker /ai-core` en `@iobroker /ai-gui`",
|
|
49
|
+
"fr": "Modifié : l'assistant IA utilise les bibliothèques partagées @iobroker /ai-core et @iobroker /ai-gui",
|
|
50
|
+
"it": "Modificato: l'AI usa le librerie condivise @iobroker /ai-core e @iobroker /ai-gui",
|
|
51
|
+
"es": "Cambiado: el asistente de IA usa las bibliotecas compartidas `@iobroker /ai-core` y `@iobroker /ai-gui`",
|
|
52
|
+
"pl": "Zmieniono: asystent AI korzysta z bibliotek współdzielonych `@iobroker /ai-core` i `@iobroker /ai-gui`",
|
|
53
|
+
"uk": "Змінено: помічник AI використовує спільні бібліотеки `@iobroker /ai-core` та `@iobroker /ai-gui`",
|
|
54
|
+
"zh-cn": "已更改:AI 助手使用共享库 @iobroker /ai-core 和 @iobroker /ai-gui"
|
|
55
|
+
},
|
|
43
56
|
"10.3.0": {
|
|
44
57
|
"en": "The code editor (Monaco), Blockly and the Rules blocks are loaded only when a script of that kind is opened, so the editor starts faster\nAdded function block diagrams (FBD, in the style of CFC): timers, counters, flip-flops, edges, comparison, arithmetic, conversions, control, calendar (cron, sun events), log and messages, and a block with own JavaScript - wired to ioBroker states. See [the description](docs/en/fbd.md)",
|
|
45
58
|
"de": "Die Blöcke Code-Editor (Monaco), Blockly und Rules werden nur geladen, wenn ein Skript geöffnet wird.\nFunktionsblockdiagramme (FBD, im CFC-Stil) hinzugefügt: Timer, Zähler, Flipflops, Kanten, Vergleich, Arithmetik, Umrechnungen, Kalender (Cron, Sun), Log und Nachrichten und ein Block mit eigenem JavaScript — mit ioBroker-Status. Siehe [Beschreibung] (docs/en/fbd.md)",
|
|
@@ -117,19 +130,6 @@
|
|
|
117
130
|
"pl": "Zasady: wybór stanu stałego",
|
|
118
131
|
"uk": "Правила: вибір штату фіксований",
|
|
119
132
|
"zh-cn": "规则:选州固定"
|
|
120
|
-
},
|
|
121
|
-
"10.2.0": {
|
|
122
|
-
"en": "Rules: an empty \"and\" band folds down to its heading. A rule without conditions runs its actions on every trigger, but that band was still the tallest thing in the rule - a drop area with a 64px floor, the \"just check\" selector and an \"or\" row per group, 292px for nothing. It is 41px now and says \"without condition\", clicking the heading opens it again, dragging a condition over it opens it by itself, and a band that has conditions in it never folds\nRules: the block palette takes half the room it did. An entry carried 24px of padding around a 30px icon, which left 66px of sidebar for one line of text - so four blocks filled the whole height and everything else was behind a scrollbar. Entries are 31px apart now, the icon-only tabs above them no longer reserve the height of a label they do not have, and the sidebar is 168px instead of 200px wide. A name too long for that gets the full text as its tooltip. The button that folds the palette away also sits on the palette's line now instead of one pixel to the left of it, where it hung over the edge of the window once the palette was folded away\nRules: picking the state of a trigger took the editor down with \"n.replace is not a function\" when a condition on a string state had no value entered yet. Choosing a state compiles the whole rule again, and the empty value arrived at the comparison as the boolean `false`. A condition without a value now compares against an empty text, and a number entered for a state that is a string is used as its text\nThe script editor now tells the adapter every 10 seconds that it is open, and the adapter keeps the type definitions and the compiler hot while that is the case, so saving a script does not wait for them to be built again. 30 seconds after the last sign of life the GUI counts as gone and everything is given back - about 100 MB. A tab in the background does not count as open, so a forgotten browser tab cannot keep the memory alive for days (#2373)\nThe type definitions of Node.js, ioBroker and the configured libraries were read at every start, whether anything wanted them or not. Only two things do - compiling a TypeScript script and the built-in editor - and they add about 90 MB to the compiler, so they are now read when one of those actually asks. An instance that runs plain JavaScript and is edited elsewhere (mirror directory, external editor) never reads them; the declarations of global JavaScripts are generated without them and come out the same. They can also be switched off for good (\"Load type definitions\", TypeScript tab) - the editor then loses its autocompletion and TypeScript scripts no longer compile, which the adapter warns about in the log (#2373)\nEvery instance kept two TypeScript language services alive whether it needed them or not, and each one held on to about 95 MB once it had compiled anything. They are now built on the first compilation only, and the declarations of global JavaScripts are stored on the script object the same way compiled TypeScript sources already were - so a restart no longer regenerates them. What a language service does end up building is released again a minute after the last compilation and rebuilt on demand. On a test system this took an instance from 241 MB to 127 MB heap (352 MB to 233 MB RSS) (#2373)\nThe helpers that the script editor draws on its own - the \"Explain / Refactor / Test\" row above every function, the tooltips for object IDs and CRON expressions, and the inline code suggestions - can be switched off. The instance setting \"Show AI helpers in the script editor\" (AI settings) does it; it is on by default, so nothing changes for anyone who is happy with them. `Alt+I` still shows the value of the object ID under the cursor when they are off\nThe reasoning of an OpenAI-compatible endpoint was switched off unconditionally: `reasoning_effort: \"none\"` went out with every request as soon as a custom base URL was configured. That is right for a small local model and wrong for everything else - behind a proxy it turns off the reasoning of the very model one is paying for, or is rejected. It is a setting now (\"Reasoning effort\"), and the default leaves the parameter out and lets the endpoint decide\nThe AI editor told the adapter how long it was willing to wait, and the adapter never read it: a stuck inline completion held its slot for the full ten minutes instead of the fifteen seconds it asked for\nThe inline completion took the model chosen in the AI chat but picked the provider itself, so a model of one provider could be requested with the credentials and at the endpoint of another. Model and provider are now remembered and used together\nWhen two providers offer a model of the same name - a proxy and the vendor behind it, for instance - which of them served it was decided by whichever answered first, and could change from one reload to the next. The provider configured first wins now, so the direct route is preferred over a proxy",
|
|
123
|
-
"de": "Regeln: Ein leeres „Und“ -Band klappt nach unten. Eine Regel ohne Bedingungen führt ihre Aktionen bei jedem Auslöser aus, aber das Band war immer noch am höchsten — ein Drop-Bereich mit 64 Pixeln, „Just check“ -Selektor und „oder“ -Reihe pro Gruppe, 292 px umsonst. Es ist jetzt 41 Pixel groß und sagt „ohne Bedingung“. Ein Klick auf die Überschrift öffnet sie erneut, und ein Band mit Bedingungen klappt nie.\nRegeln: Die Blockpalette nimmt halb so viel Platz ein. Ein Eintrag war 24 px rund um ein 30-Pix-Symbol, sodass 66 px Seitenleiste für eine Textzeile übrig waren — vier Blöcke füllten die ganze Höhe und alles andere war hinter einer Scrollleiste. Die Einträge sind jetzt 31 Pixel auseinander, die Tabs über ihnen haben keine Labelhöhe mehr und die Seitenleiste ist 168 Pixel statt 200 Pixel breit. Ein zu langer Name hat den Volltext als Tooltip. Die Schaltfläche zum Einklappen der Palette befindet sich jetzt auch auf der Linie der Palette und nicht ein Pixel links davon, wo sie nach dem Zusammenklappen über dem Fensterrand hing\nRegeln: Wenn der Status eines Triggers noch kein Wert eingegeben wurde, sagte der Editor „n.replace ist keine Funktion“. Wenn Sie ein Bundesland wählen, wird die Regel erneut kompiliert, und der leere Wert ergab den booleschen Wert Eine Bedingung ohne Wert wird nun mit leerem Text verglichen, und als Text wird eine Zahl für ein Bundesland verwendet\nDer Skripteditor teilt dem Adapter nun alle 10 Sekunden mit, dass er geöffnet ist, und hält dabei die Typdefinitionen und den Compiler heiß. Das Speichern eines Skripts wartet nicht, bis es neu erstellt wird. 30 Sekunden nach dem letzten Lebenszeichen gilt die GUI als weg und alles wird zurückgegeben — etwa 100 MB. Ein Tab im Hintergrund gilt nicht als geöffnet, ein vergessener Browser-Tab hält ihn tagelang fest (#2373)\nDie Typdefinitionen von Node.js, ioBroker und die konfigurierten Bibliotheken wurden bei jedem Start gelesen. Nur zwei Dinge tun das — ein TypeScript-Skript und der eingebaute Editor — und sie erhöhen den Compiler um 90 MB, sodass sie gelesen werden, wenn einer fragt. Eine Instanz, die reines JavaScript ausführt und woanders bearbeitet wird (Spiegelverzeichnis, externer Editor), liest sie nie. Die Deklarationen globaler JavaScripts werden ohne sie generiert. Sie sind auch endgültig abschaltbar („Load Type Definitions“, Tab TypeScript) — dann verliert der Editor seine Autokomplettierung und TypeScript-Skripte kompilieren nicht mehr, wovor der Adapter warnt (#2373)\nJede Instanz hielt zwei TypeScript-Sprachdienste am Leben, ob nötig oder nicht, und jede hielt etwa 95 MB, nachdem sie etwas kompiliert hatte. Sie basieren jetzt nur auf der ersten Compilierung und globale JavaScript-Deklarationen werden im Skriptobjekt gespeichert, so dass sie bei einem Neustart nicht mehr neu generiert werden. Was ein Sprachdienst baut, wird eine Minute nach der letzten Compilation erneut veröffentlicht. Auf einem Testsystem waren es 241 MB auf 127 MB Heap (352 MB bis 233 MB RSS) (#2373)\nDie vom Skripteditor selbst erstellten Helfer — die Zeile „Explain/Refactor/Test“ über jeder Funktion, Tooltips für Objekt-IDs und CRON-Ausdrücke und Inline-Codevorschläge — können abgeschaltet werden. Die Instanzeinstellung „Zeige KI-Helfer im Skripteditor“ (AI-Einstellungen) tut das. Sie ist standardmäßig aktiviert, also ändert sich nichts. `Alt+I` zeigt auch bei ausgeschaltetem Cursor den Wert der Objekt-ID\nDie Logik eines OpenAI-fähigen Endpunkts wurde bedingungslos abgeschaltet: `reasoning_effort: „none\"` ging bei jeder Anfrage raus, sobald eine benutzerdefinierte Basis-URL konfiguriert war. Das stimmt für ein kleines Lokalmodell und falsch für alles andere. Hinter einem Proxy steht das Modell, für das man bezahlt, oder es wird abgelehnt. Es ist jetzt eine Einstellung („Argumentationsaufwand“), ohne Parameter und der Endpunkt entscheidet\nDer KI-Editor teilte dem Adapter mit, wie lange er bereit war zu warten, und der Adapter las ihn nie: Ein hängengebliebener Inline-Slot hielt die vollen zehn Minuten statt 15 Sekunden\nBeim Inline-Abschluss wurde das im KI-Chat gewählte Modell, aber der Anbieter selbst ausgewählt, sodass ein Modell mit den Zugangsdaten und am Ende eines anderen angefragt werden konnte. Modell und Anbieter werden nun gespeichert und genutzt\nWenn zwei Anbieter ein Modell mit dem gleichen Namen anbieten, z. B. einen Proxy und den Anbieter dahinter, entscheidet, wer zuerst antwortet, und kann von einem Reload zum nächsten wechseln. Der erste Anbieter gewinnt jetzt, der direkte Weg wird einem Proxy vorgezogen",
|
|
124
|
-
"ru": "Правила: пустая полоса «и» сворачивается к заголовку. Правило без условий срабатывает при каждом триггере, но эта полоса всё равно оставалась самой высокой в правиле — зона выпадения с полом размером 64 пикселя, селектор «просто галочка» и строка «или» на группу, 292 пикселя даром. Теперь оно составляет 41 пиксель и написано «без условий», при нажатии на заголовок оно снова открывается, при перетаскивании условия оно открывается само по себе, а полоса, в которой есть условия, никогда не сворачивается\nПравила: блочная палитра занимает вдвое меньше места, чем раньше. Значок размером 30 пикселей составлял 24 пикселя, в результате чего на одной строке текста оставалось 66 пикселей боковой панели. Таким образом, четыре блока заполнили всю высоту, а все остальное — за полосой прокрутки. Теперь расстояние между записями составляет 31 пиксель, а расположенные над ними вкладки, содержащие только значки, больше не сохраняют высоту метки, которой у них нет, а ширина боковой панели составляет 168 пикселей вместо 200 пикселей. При слишком длинном названии в виде всплывающей подсказки отображается полный текст. Кнопка, откидывающая палитру, теперь также находится на линии палитры, а не на одном пикселе слева от нее. Как только палитра была сложена, она висела над краем окна\nПравила: при выборе состояния триггера редактор выводил сообщение «n.replace is not a function», когда условие в строковом состоянии еще не было введено ни одного значения. При выборе состояния все правило снова компилируется, а пустое значение при сравнении выводится как логическое значение «false». Условие без значения теперь сравнивается с пустым текстом, а в качестве текста используется число, введенное для состояния, представляющего собой строку\nТеперь редактор сценариев сообщает адаптеру каждые 10 секунд о том, что он открыт, а определения типов и компилятор остаются в рабочем состоянии, поэтому сохранение скрипта не дожидается его повторной сборки. Через 30 секунд после появления последних признаков жизни графический интерфейс считается исчерпанным и все возвращено обратно — около 100 МБ. Вкладка в фоновом режиме не считается открытой, поэтому забытая вкладка браузера не сможет сохранить память в течение нескольких дней (#2373)\nОпределения типов Node.js, IOBroker и настроенных библиотек считывались при каждом запуске, независимо от того, хотели они того или нет. Только две вещи — компиляция сценария TypeScript и встроенного редактора — и они добавляют компилятору около 90 МБ, поэтому теперь они читаются, когда кто-то из них действительно запрашивает. Экземпляр, работающий под управлением обычного JavaScript и редактируемый в другом месте (зеркальный каталог, внешний редактор), никогда не читает их; объявления глобальных JavaScripts генерируются без них и получаются одинаковыми. Их также можно навсегда отключить («Загрузить определения типов», вкладка TypeScript) — в этом случае редактор теряет автозаполнение, а скрипты TypeScript перестают компилироваться, о чем адаптер предупреждает в журнале (#2373)\nВ каждом экземпляре две языковые службы TypeScript работали независимо от того, были ли они нужны или нет, и каждая из них после компиляции занимала около 95 МБ. Теперь они основаны только на первой компиляции, а объявления глобальных JavaScript хранятся в объекте сценария так же, как и скомпилированные исходники TypeScript, поэтому при перезапуске они больше не восстанавливаются. То, что в конечном итоге создает языковой сервис, снова публикуется через минуту после последней компиляции и перестраивается по запросу. В тестовой системе объем кучи в экземпляре составлял от 241 МБ до 127 МБ (с 352 МБ до 233 МБ в формате RSS) (#2373)\nПомощники, которые редактор сценариев использует самостоятельно — строку «Explain/Refactor/Test» над каждой функцией, всплывающие подсказки для идентификаторов объектов и выражений CRON, а также встроенные рекомендации по коду — можно отключить. Параметр экземпляра «Показать помощников искусственного интеллекта в редакторе сценариев» (настройки ИИ) работает; по умолчанию он включен, поэтому для всех, кому они нравятся, ничего не меняется. В выключенном режиме «Alt+I» по-прежнему отображается значение идентификатора объекта под курсором\nОбоснование наличия конечной точки, совместимой с OpenAI, было безоговорочно опровергнуто: `reasoning_effort: «none\"` отправлялось с каждым запросом, как только был настроен собственный базовый URL-адрес. Это верно для небольшой локальной модели и неправильно для всего остального: прокси-сервер отключает аргументы в пользу той самой модели, за которую вы платите, или отклоняется. Теперь это настройка («Усилия по обоснованию»), но по умолчанию этот параметр не используется, а решение остаётся за конечной точкой\nРедактор искусственного интеллекта сообщил адаптеру, сколько он готов ждать, но адаптер так и не прочитал его: из-за зависания в строке ввода слот удерживался целых десять минут, а не пятнадцать секунд, как того требовалось\nПри заполнении в интерактивном режиме использовалась модель, выбранная в чате с искусственным интеллектом, но выбирался сам поставщик, поэтому можно было запросить модель одного поставщика с учетными данными и на конечной точке другого. Теперь модель и провайдер запоминаются и используются вместе\nКогда два провайдера предлагают модель с одинаковым названием (например, прокси-сервер и поставщик, стоящий за ним), выбор того, кто из них обслужил, решал тот, кто ответил первым, и может меняться от одной перезагрузки к следующей. Теперь выигрывает тот провайдер, который настроил первым, поэтому предпочтение отдается прямому маршруту, а не прокси-серверу",
|
|
125
|
-
"pt": "Regras: uma faixa “e” vazia se dobra até o título. Uma regra sem condições executa suas ações em cada gatilho, mas essa faixa ainda era a mais alta: uma área de 64 px, o seletor “just check” e uma linha “ou” por grupo, 292 px à toa. Agora tem 41px e diz “sem condição”, clicar no título a abre novamente, arrastar uma condição sobre ela a abre sozinha, e uma faixa com condições nunca se dobra\nRegras: a paleta de blocos ocupa metade. Uma entrada tinha 24px de espaço em torno de um ícone de 30px, deixando 66px de barra lateral para uma linha de texto — então quatro blocos ocupavam toda a altura e rolavam. As entradas estão separadas por 31 px, as abas com ícones não têm mais a altura de um rótulo que não têm e a barra lateral tem 168 px em vez de 200 px. Um nome longo demais tem o texto completo como dica. O botão que dobra a paleta também fica na linha da paleta agora, em vez de um pixel à esquerda, onde ficava na borda da janela quando a paleta era dobrada.\nRegras: escolher o estado de um gatilho dizia “n.replace is not a function” quando uma condição em uma string ainda não tinha valor inserido. A escolha de um estado compila toda a regra e o valor vazio chegou à comparação como booleano `false`. Uma condição sem valor agora se compara a um texto vazio e um número inserido em uma string é usado como texto\nO editor de scripts agora informa ao adaptador a cada 10 segundos que ele está aberto, e o adaptador mantém as definições de tipo e o compilador ativos. Salvar um script não espera que ele seja reconstruído. 30 segundos após o último sinal de vida, a GUI é considerada perdida e tudo é devolvido - cerca de 100 MB. Uma aba no fundo não conta como aberta, então uma aba esquecida não mantém a memória viva por dias (#2373)\nAs definições de tipo de Node.js, IOBroker e das bibliotecas configuradas foram lidas sempre, querendo ou não. Apenas duas coisas — compilar um script TypeScript e um editor embutido — adicionam cerca de 90 MB ao compilador e agora são lidos quando alguém pede. Uma instância que executa JavaScript puro e é editada em outro lugar (diretório espelho, editor externo) nunca os lê; as declarações de JavaScripts globais são geradas sem elas e saem iguais. Eles também podem ser desativados para sempre (“Definições de tipo de carga”, guia TypeScript) - o editor perde o preenchimento automático e os scripts não são mais compilados, o que o adaptador avisa no log (#2373)\nCada instância mantinha dois serviços da linguagem TypeScript ativos, precisando ou não, e cada um tinha cerca de 95 MB após compilar algo. Agora, elas se baseiam apenas na primeira compilação e as declarações globais de JavaScript são armazenadas no objeto de script da mesma forma que as fontes compiladas do TypeScript. O que um serviço de linguagem cria é lançado um minuto após a última compilação e reconstruído sob demanda. Em um sistema de teste, isso levou de 241 MB a 127 MB de heap (352 MB a 233 MB RSS) (#2373)\nOs auxiliares que o editor de script usa sozinho — a linha “Explain/Refactor /Test” acima de cada função, as dicas para IDs de objetos e expressões CRON e as sugestões de código — podem ser desativados. A configuração de instância “Mostrar ajudantes de IA no editor de scripts” faz isso; ela está ativada por padrão, então nada muda para quem gosta deles. `Alt+I` ainda mostra o valor do ID do objeto sob o cursor quando desligado\nO raciocínio de um endpoint compatível com OpenAI era incondicional: `reasoning_effort: “none\"` saía com cada solicitação assim que um URL base customizado era configurado. Isso é certo para um modelo local pequeno e errado para todo o resto: por trás de um proxy, ele desativa o raciocínio do modelo pelo qual se paga ou é rejeitado. Agora é uma configuração (“Reasoning effort”), e o padrão exclui o parâmetro e deixa o endpoint decidir\nO editor de IA disse ao adaptador quanto tempo ele estava disposto a esperar e ele nunca o leu: um preenchimento em linha travado manteve o slot por dez minutos, em vez dos quinze segundos necessários\nO preenchimento em linha usou o modelo escolhido no chat de IA, mas escolheu o provedor em si, para solicitar o modelo de um provedor com as credenciais e no terminal de outro. Modelo e provedor agora são lembrados e usados juntos\nQuando dois provedores oferecem um modelo com o mesmo nome — um proxy e o fornecedor por trás dele — qual deles atendia, quem respondia primeiro e pode mudar de uma recarga para outra. O primeiro provedor vence agora, então a rota direta é preferida a um proxy",
|
|
126
|
-
"nl": "Regels: een lege „en” band kan naar beneden worden gevouwen tot aan de kop. Een regel zonder voorwaarden voert op elke trigger zijn acties uit, maar die band was nog steeds het grootste punt in de regel: een dropzone met een vloer van 64 px, de selector „even checken” en een rij „of” per groep, 292 px voor niets. Het is nu 41 px en er staat „zonder voorwaarde”. Als u op de kop klikt, wordt de toestand weer geopend, als u een voorwaarde eroverheen sleept, wordt deze vanzelf geopend, en een band met voorwaarden wordt nooit gevouwen\nRegels: het blokpalet neemt de helft van de ruimte in beslag. Een item bevatte 24 px opvulling rond een pictogram van 30 px, waardoor er 66 px aan zijbalk overbleef voor één regel tekst - dus vier blokken vulden de hele hoogte en al het andere zat achter een schuifbalk. De items staan nu 31 pixels uit elkaar, op de tabbladen met alleen pictogrammen erboven is niet langer de hoogte gereserveerd van een label dat ze niet hebben, en de zijbalk is 168 px in plaats van 200 px breed. Een naam die te lang is daarvoor, krijgt de volledige tekst als tooltip. De knop waarmee het palet wordt weggevouwen, bevindt zich nu ook op de lijn van het palet, in plaats van één pixel links ervan, waar hij boven de rand van het venster hing toen het palet was weggevouwen\nRegels: door de status van een trigger te kiezen, werd de editor uitgeschakeld met „n.replace is geen functie” toen er nog geen waarde was ingevoerd voor een voorwaarde op basis van een tekenreeks. Als u een staat kiest, wordt de hele regel opnieuw gecompileerd, en de lege waarde kwam tot de vergelijking als de booleaanse waarde `false`. Een voorwaarde zonder waarde wordt nu vergeleken met een lege tekst, en een getal dat is ingevoerd voor een staat, dat een tekenreeks is, wordt als tekst gebruikt\nDe scripteditor laat de adapter nu elke 10 seconden weten dat deze open is, en de adapter houdt de typedefinities en de compiler actief terwijl dat het geval is, dus als u een script opslaat, hoeft u niet te wachten tot ze opnieuw worden gebouwd. 30 seconden na het laatste teken van leven telt de GUI als verdwenen en wordt alles teruggegeven - ongeveer 100 MB. Een tabblad op de achtergrond telt niet als geopend, dus een vergeten browsertabblad kan de herinnering niet dagenlang levend houden (#2373)\nDe typedefinities van Node.js, IOBroker en de geconfigureerde bibliotheken werden bij elke start gelezen, of iemand ze nu wilde of niet. U kunt maar twee dingen doen: een TypeScript-script compileren en de ingebouwde editor, en ze voegen ongeveer 90 MB toe aan de compiler, zodat ze nu worden gelezen wanneer een van hen dat daadwerkelijk vraagt. In een exemplaar dat gewoon JavaScript draait en elders wordt bewerkt (mirror directory, externe editor) worden ze nooit gelezen; de declaraties van globale JavaScripts worden zonder JavaScript gegenereerd en komen op dezelfde manier uit. Ze kunnen ook voorgoed worden uitgeschakeld („Typedefinities laden”, tabblad TypeScript) - de editor wordt dan niet meer automatisch aangevuld en TypeScript-scripts worden niet meer gecompileerd, waarvoor de adapter waarschuwt in het logboek (#2373)\nElke instantie hield twee TypeScript-taaldiensten in leven, of ze nu nodig waren of niet, en elke service had een capaciteit van ongeveer 95 MB toen er iets was gecompileerd. Ze zijn nu alleen gebaseerd op de eerste compilatie, en de declaraties van wereldwijde JavaScripts worden op het scriptobject opgeslagen op dezelfde manier als de gecompileerde TypeScript-bronnen dat al deden, zodat ze na een herstart niet langer opnieuw worden gegenereerd. Wat een taaldienst uiteindelijk bouwt, wordt een minuut na de laatste compilatie opnieuw uitgebracht en op aanvraag opnieuw opgebouwd. Op een testsysteem duurde dit een heap van 241 MB naar 127 MB (352 MB tot 233 MB RSS) (#2373)\nDe helpers die de scripteditor zelf tekent - de rij „Explain/Refactor/Test” boven elke functie, de tooltips voor object-ID's en CRON-expressies, en de suggesties voor inline-code - kunnen worden uitgeschakeld. De instantie-instelling „AI-helpers weergeven in de scripteditor” (AI-instellingen) doet dit; de instelling is standaard ingeschakeld, dus er verandert niets voor iedereen die er tevreden mee is. In `Alt+I` wordt nog steeds de waarde van de object-ID onder de cursor weergegeven als ze uitgeschakeld zijn\nDe redenering van een OpenAI-compatibel eindpunt werd onvoorwaardelijk uitgeschakeld: `reasoning_effort: „none\"` werd bij elk verzoek verzonden zodra een aangepaste basis-URL was geconfigureerd. Dat is goed voor een klein lokaal model en verkeerd voor al het andere - achter een proxy wordt de redenering uitgeschakeld van het model waarvoor men betaalt, of dat wordt afgewezen. Het is nu een instelling („Reasoning effort”), en de standaardinstelling laat de parameter weg en laat het eindpunt beslissen\nDe AI-redacteur vertelde de adapter hoelang hij bereid was te wachten, en de adapter heeft hem nooit gelezen: een vastzittende inline-voltooiing hield de volledige tien minuten vast in plaats van de vijftien seconden waar hij om vroeg\nVoor de inline-voltooiing werd het model gebruikt dat werd gekozen in de AI-chat, maar de provider zelf, zodat een model van de ene provider kon worden aangevraagd met de inloggegevens en op het eindpunt van een andere provider. Model en provider worden nu onthouden en samen gebruikt\nAls twee providers een model met dezelfde naam aanbieden, bijvoorbeeld een proxy en de leverancier die erachter zit, werd besloten wie van hen bediende, door de persoon die het eerst werd geantwoord, en kon van de ene herlaadbeurt naar de andere worden overgeschakeld. De provider die als eerste is geconfigureerd wint nu, dus de directe route heeft de voorkeur boven een proxy",
|
|
127
|
-
"fr": "Règles : un bandeau vide se replie jusqu'au titre. Une règle sans conditions agit sur chaque déclencheur, mais cette bande était la plus haute de la règle : une zone de dépôt avec un sol de 64 pixels, le sélecteur « juste cocher » et une ligne « ou » par groupe, 292 pixels pour rien. Il fait 41 pixels maintenant et dit « sans condition ». Cliquez sur le titre pour l'ouvrir à nouveau, le faire glisser dessus l'ouvre tout seul, et une bande contenant des conditions ne se plie jamais\nRègles : la palette de blocs occupe la moitié de la place. Une entrée comportait 24 pixels de marge autour d'une icône de 30 pixels, soit 66 pixels de barre latérale pour une ligne de texte. Quatre blocs occupaient toute la hauteur et le reste était placé derrière une barre de défilement. Les entrées sont espacées de 31 pixels, les icônes situées au-dessus n'ont plus la même hauteur que les étiquettes, et la barre latérale mesure 168 pixels au lieu de 200 pixels. Un nom trop long affiche le texte intégral en infobulle. Le bouton qui replie la palette se trouve également sur la ligne de la palette, au lieu d'un pixel sur la gauche, où il pendait au-dessus du bord de la fenêtre une fois la palette pliée\nRègles : choisir l'état d'un déclencheur renvoyait l'éditeur avec « n.replace is not a function » alors qu'aucune valeur n'avait encore été saisie. Le choix d'un état recompile la règle complète, et la valeur vide est arrivée à la comparaison sous la forme booléenne « false ». Une condition sans valeur est désormais comparée à un texte vide, et un chiffre saisi pour un état qui est une chaîne est utilisé comme texte\nL'éditeur de script indique désormais à l'adaptateur toutes les 10 secondes qu'il est ouvert, et l'adaptateur garde les définitions de type et le compilateur à chaud. Enregistrer un script ne nécessite donc pas qu'il soit reconstruit. 30 secondes après le dernier signe de vie, l'interface graphique est considérée comme perdue et tout est rendu, soit environ 100 Mo. Un onglet en arrière-plan n'est pas considéré comme ouvert, donc un onglet oublié ne peut pas le garder en mémoire (#2373)\nLes définitions de type de Node.js, IObroker et des bibliothèques configurées étaient lues à chaque démarrage, que cela soit voulu ou non. Il n'y a que deux choses à faire : compiler un script TypeScript et l'éditeur intégré. Ils ajoutent environ 90 Mo au compilateur. Ils sont donc lus dès que l'un d'eux le demande. Une instance qui exécute du JavaScript et qui est modifiée ailleurs (répertoire miroir, éditeur externe) ne les lit jamais ; les déclarations des JavaScript globaux sont générées sans elles et sortent identiques. Ils peuvent aussi être définitivement désactivés (« Charger les définitions de type », onglet TypeScript). L'éditeur perd alors son autocomplétion et les scripts TypeScript ne sont plus compilés, comme l'adaptateur le signale dans le log (#2373)\nChaque instance maintenait deux services linguistiques TypeScript actifs, qu'elle en ait besoin ou non, et chacune conservait environ 95 Mo une fois compilé. Ils ne sont créés que sur la première compilation, et les déclarations des scripts globaux sont stockées dans l'objet de script, de la même manière que les sources TypeScript compilées. Un redémarrage ne les régénère plus. What a language service does end up est réédité une minute après la dernière compilation et reconstruit à la demande. Sur un système de test, il a passé de 241 Mo à 127 Mo (352 Mo à 233 Mo de RSS) (#2373)\nLes aides créées par l'éditeur de script lui-même (la ligne « Expliquer/Refactor/Test » au-dessus de chaque fonction, les info-bulles pour les ID d'objets et les expressions CRON et les suggestions de code en ligne) peuvent être désactivées. Le paramètre d'instance « Afficher les assistants IA dans l'éditeur de script » (paramètres d'IA) le fait ; il est activé par défaut, donc rien ne change pour les satisfaits. `Alt+I` affiche toujours la valeur de l'ID de l'objet sous le curseur éteint\nLe raisonnement d'un point de terminaison compatible avec OpenAI a été désactivé : « reasoning_effort : « none » est envoyé à chaque demande dès qu'une URL de base personnalisée a été configurée. C'est bien pour un petit modèle local et c'est faux pour tout le reste. Un proxy désactive le raisonnement du modèle même pour lequel on paie, ou il est rejeté. C'est un réglage maintenant (« Effort de raisonnement »), et par défaut, c'est le point final qui décide\nL'éditeur d'IA a indiqué à l'adaptateur combien de temps il était prêt à attendre, mais celui-ci ne l'a jamais lu : une page bloquée a tenu sa place pendant dix minutes au lieu des quinze secondes demandées\nLa saisie en ligne a pris le modèle choisi dans le chat IA, mais le fournisseur lui-même. Ainsi, le modèle d'un fournisseur pouvait être demandé avec les informations d'identification et un autre. Le modèle et le fournisseur sont désormais mémorisés\nLorsque deux fournisseurs proposent un modèle du même nom, un proxy et le fournisseur qui le propose, par exemple, celui qui le proposait était décidé en premier, et pouvait changer d'un rechargement à l'autre. Le fournisseur configuré First gagne, donc la route directe est préférée à un proxy",
|
|
128
|
-
"it": "Regole: una banda «e» vuota si piega fino al titolo. Una regola senza condizioni agisce su ogni trigger, ma quella banda era comunque la più alta della regola: un'area di caduta con 64 px, selettore «just check» e una riga «o» per gruppo, 292 px. Ora è di 41 px e dice «senza condizioni», facendo clic sul titolo si apre di nuovo, trascinando una condizione si apre da sola e una banda con condizioni non si piega mai\nRegole: la palette occupa metà dello spazio. Una voce aveva 24 px di padding su un'icona di 30 px, con 66 px di barra laterale per una riga di testo, quattro blocchi e tutto il resto dietro una barra di scorrimento. Le voci ora distano 31 px, le schede con sole icone non hanno più l'altezza di un'etichetta che non hanno e la barra laterale è larga 168 px invece di 200 px. Un nome troppo lungo per avere il testo completo. Il pulsante che ripiega la palette ora si trova anche sulla linea della palette invece di un pixel a sinistra, dove era appeso sul bordo della finestra\nRegole: selezionando lo stato di un trigger, l'editor ha digitato «n.replace is not a function» se una condizione in una stringa non era ancora valida. La scelta di uno stato ricompila l'intera regola e il valore vuoto è booleano `false`. Una condizione senza valore ora si confronta con un testo vuoto e come testo si usa un numero immesso per uno stato che è una stringa\nL'editor di script ora dice all'adattatore ogni 10 secondi che è aperto e mantiene le definizioni dei tipi e il compilatore attivi finché è così, quindi salvare uno script non aspetta che vengano ricreati. 30 secondi dopo l'ultimo segno di vita la GUI conta come sparita e tutto viene restituito: circa 100 MB. Una scheda in background non è aperta, quindi una scheda dimenticata non può durare giorni (#2373)\nLe definizioni dei tipi di Node.js, IOBroker e le librerie configurate venivano lette ad ogni avvio, che lo volesse o no. Solo due cose, compilare uno script TypeScript e l'editor integrato, aggiungono circa 90 MB al compilatore, quindi ora vengono letti quando uno lo chiede. Un'istanza in JavaScript semplice e modificata altrove (mirror directory, editor esterno) non li legge mai; le dichiarazioni di JavaScript globali sono generate senza di esse e sono uguali. Possono anche essere disattivati per sempre («Load type definition», scheda TypeScript): l'editor perde l'autocompletamento e gli script TypeScript non vengono più compilati, cosa che l'adattatore avvisa nel log (#2373)\nOgni istanza manteneva attivi due servizi TypeScript, che ne avesse bisogno o meno, e ognuno conteneva circa 95 MB dopo aver compilato qualcosa. Ora si basano solo sulla prima compilazione e le dichiarazioni dei JavaScript globali sono archiviate nell'oggetto script come già i sorgenti TypeScript compilati, quindi un riavvio non li rigenera più. Ciò che un servizio linguistico crea viene rilasciato un minuto dopo l'ultima compilazione e ricostruito su richiesta. Su un sistema di test ci sono voluti da 241 MB a 127 MB heap (da 352 MB a 233 MB RSS) (#2373)\nGli helper che l'editor di script utilizza da solo, la riga «Explan/Refactor/Test» sopra ogni funzione, i tooltip per ID oggetto ed espressioni CRON e il codice in linea, possono essere disattivati. L'impostazione «Mostra aiutanti AI nell'editor di script» (impostazioni AI) lo fa; è attiva di default, quindi non cambia nulla per chi ne è soddisfatto. `Alt+I` mostra ancora il valore dell'ID oggetto quando sono spenti\nLa logica di un endpoint compatibile con OpenAI è stata disattivata incondizionatamente: «none» è uscito con ogni richiesta non appena è stato configurato un URL di base personalizzato. È giusto per un piccolo modello locale e sbagliato per tutto il resto: dietro un proxy spegne il ragionamento del modello per cui si paga o viene rifiutato. Ora è un'impostazione («Reasoning effort») e di default omette il parametro e decide l'endpoint\nL'editor AI ha detto all'adattatore quanto era disposto ad aspettare e l'adattatore non l'ha mai letto: un completamento in linea bloccato è durato dieci minuti invece dei quindici richiesti\nIl completamento in linea ha utilizzato il modello scelto nella chat AI ma il provider stesso, quindi richiederne uno con le credenziali e l'endpoint di un altro. Modello e fornitore sono ora ricordati e usati insieme\nQuando due provider offrono un modello con lo stesso nome, un proxy e il fornitore dietro, ad esempio, chi lo ha fornito è deciso per primo e può passare da una ricarica all'altra. Il provider configurato per primo vince ora, quindi preferisce il proxy",
|
|
129
|
-
"es": "Reglas: una banda vacía con «y» se dobla hasta su título. Una regla sin condiciones ejecuta sus acciones en cada activación, pero esa banda seguía siendo la más alta de la regla: un área desplegable con un suelo de 64 píxeles, el selector de «solo comprobar» y una fila «o» por grupo, 292 píxeles para nada. Ahora mide 41 píxeles y dice «sin condiciones». Al hacer clic en el encabezado, se abre de nuevo, al arrastrar una condición, se abre sola y una banda con condiciones nunca se dobla\nReglas: la paleta de bloques ocupa la mitad. Una entrada tenía 24 píxeles de relleno alrededor de un icono de 30 píxeles, lo que dejaba 66 píxeles en la barra lateral para una línea de texto. Cuatro bloques llenaban toda la altura y todo lo demás detrás de una barra de desplazamiento. Las entradas están separadas por 31 píxeles, las pestañas de solo iconos ya no tienen el alto de una etiqueta que no tienen y la barra lateral mide 168 píxeles en lugar de 200 píxeles. Un nombre demasiado largo para eso tiene el texto completo. El botón que dobla la paleta también está ahora en la línea de la paleta, en lugar de un píxel a la izquierda, donde colgaba del borde de la ventana una vez doblada la paleta\nReglas: al elegir el estado de un disparador, el editor decía «n.replace no es una función» cuando una condición del estado de la cadena aún no tenía ningún valor. Al elegir un estado, se vuelve a compilar toda la regla y el valor vacío llegó a la comparación como el booleano «falso». Una condición sin valor ahora se compara con un texto vacío y se utiliza como texto un número introducido para un estado, es decir, una cadena\nEl editor de guiones ahora le dice al adaptador cada 10 segundos que está abierto y mantiene las definiciones de tipos y el compilador activos, por lo que guardar un guion no espera a que se vuelva a crear. 30 segundos después de la última señal de vida, la GUI cuenta como agotada y todo se devuelve, unos 100 MB. Una pestaña en segundo plano no cuenta como abierta, por lo que olvidar no puede mantener la memoria viva durante días (#2373)\nLas definiciones de tipos de Node.js, IOBroker y las bibliotecas configuradas se leían al principio, tanto si algo las quería como si no. Solo hay dos cosas, compilar un guion de TypeScript y el editor integrado, y añaden unos 90 MB al compilador, por lo que ahora se leen cuando uno de esos pregunta. Una instancia que ejecuta JavaScript simple y se edita en otro lugar (directorio espejo, editor externo) nunca los lee; las declaraciones de los JavaScript globales se generan sin ellos y salen igual. También se pueden desactivar definitivamente («Cargar definiciones de tipos», pestaña TypeScript). El editor pierde su autocompletado y los guiones de TypeScript ya no se compilan, lo que el adaptador avisa en el registro (#2373)\nCada instancia mantuvo activos dos servicios lingüísticos de TypeScript, los necesitara o no, y cada uno conservó unos 95 MB una vez compilado algo. Ahora se basan únicamente en la primera compilación y las declaraciones de los JavaScript globales se almacenan en el objeto de script de la misma manera que ya lo hacían las fuentes de TypeScript compiladas, por lo que al reiniciarlas ya no las regenera. Lo que un servicio lingüístico acaba creando se publica de nuevo un minuto después del último recopilatorio y se reconstruye a pedido. En un sistema de prueba, una instancia pasó de 241 MB a 127 MB (352 MB a 233 MB RSS) (#2373)\nLos ayudantes que el editor de guiones dibuja por sí solo (la fila «Explicar/Refactor/Probar» sobre cada función, la información de los ID de objetos y las expresiones CRON y las sugerencias de código en línea) se pueden desactivar. El ajuste de instancia «Mostrar ayudantes de IA en el editor de guiones» (ajustes de IA) lo hace; está activado por defecto, así que nada cambia para quien esté contento con ellos. `Alt+I` sigue mostrando el valor del ID del objeto bajo el cursor cuando está desactivado\nEl razonamiento de un punto final compatible con OpenAI se desactivó incondicionalmente: `reasoning_effort: «ninguna» en cada solicitud tan pronto como se configuró una URL base personalizada. Eso es correcto para un modelo local pequeño e incorrecto para todo lo demás. Detrás de un poder se desactiva el razonamiento del mismo modelo por el que se paga o se rechaza. Ahora es un ajuste («Esfuerzo de razonamiento») y por defecto omite el parámetro y deja que el punto final decida\nEl editor de IA le dijo al adaptador cuánto tiempo estaba dispuesto a esperar y el adaptador nunca lo leyó: un atasco al completar en línea mantuvo su espacio durante diez minutos en lugar de los quince segundos que pedía\nLa finalización en línea tomó el modelo elegido en el chat de IA, pero eligió el propio proveedor, por lo que se pudo solicitar el modelo de un proveedor con las credenciales y en el extremo de otro. El modelo y el proveedor ahora se recuerdan y se usan juntos\nCuando dos proveedores ofrecen un modelo con el mismo nombre (un proxy y el proveedor detrás, por ejemplo) cuál de ellos sirve, lo decide el que responde primero y puede cambiar de una recarga a otra. El proveedor configurado primero gana ahora, por lo que se prefiere la ruta directa a un proxy",
|
|
130
|
-
"pl": "Zasady: pusty pasek „i” składa się do nagłówka. Reguła bez warunków uruchamia swoje działania na każdym wyzwalaczu, ale to pasmo nadal było najwyższym elementem reguły - obszar upuszczania z podłogą 64px, selektorem „po prostu sprawdź” i wierszem „lub” na grupę, 292 pikseli za darmo. Ma teraz 41 pikseli i mówi „bez warunku”, kliknięcie nagłówka otwiera go ponownie, przeciągnięcie warunku otwiera go samoistnie, a pasmo, które ma w sobie warunki, nigdy się nie składa\nZasady: paleta bloków zajmuje połowę miejsca, które zrobiła. Wpis zawierał 24px wypełnienia wokół ikony 30 pikseli, która pozostawiła 66 pikseli paska bocznego dla jednej linii tekstu - więc cztery bloki wypełniały całą wysokość, a wszystko inne znajdowało się za paskiem przewijania. Wpisy są teraz oddalone od siebie o 31 pikseli, zakładki tylko ikony nad nimi nie zastrzegają już wysokości etykiety, której nie mają, a pasek boczny ma szerokość 168 pikseli zamiast 200 pikseli. Nazwa zbyt długa na to otrzymuje pełny tekst jako podpowiedź. Przycisk, który składa paletę, znajduje się teraz na linii palety zamiast jednego piksela po lewej stronie, gdzie wisiał nad krawędzią okna po złożeniu palety\nReguły: wybranie stanu wyzwalacza spowodowało usunięcie edytora z „n.replace is not a function”, gdy warunek stanu łańcucha nie miał jeszcze wprowadzonej wartości. Wybór stanu ponownie kompiluje całą regułę, a pusta wartość dotarła do porównania jako logiczna „fałsz”. Warunek bez wartości porównuje się teraz z pustym tekstem, a liczba wprowadzona dla stanu będącego ciągiem jest używana jako jego tekst\nEdytor skryptów informuje teraz adapterowi co 10 sekund, że jest otwarty, a adapter zachowuje definicje typów i kompilator na gorąco, podczas gdy tak jest, więc zapisanie skryptu nie czeka na ich ponowne zbudowanie. 30 sekund po ostatnim znaku życia GUI liczy się jako zniknął i wszystko jest oddane - około 100 MB. Karta w tle nie jest liczona jako otwarta, więc zapomniana karta przeglądarki nie może utrzymać pamięci przy życiu przez wiele dni (#2373)\nDefinicje typów Node.js, ioBroker i skonfigurowanych bibliotek były odczytywane na każdym początku, niezależnie od tego, czy cokolwiek ich chciało, czy nie. Robią się tylko dwie rzeczy - skompilowanie skryptu TypeScript i wbudowany edytor - i dodają około 90 MB do kompilatora, więc są teraz odczytywane, gdy jeden z nich faktycznie poprosi. Instancja, która uruchamia zwykły JavaScript i jest edytowana gdzie indziej (katalog lustrzany, edytor zewnętrzny) nigdy ich nie czyta; deklaracje globalnych JavaScript są generowane bez nich i wychodzą tak samo. Można je również wyłączyć na dobre („Definicje typów obciążenia”, karta TypeScript) - edytor traci wtedy automatyczne uzupełnianie i skrypty TypeScript przestają się kompilować, o czym adapter ostrzega w dzienniku (#2373)\nKażda instancja utrzymywała przy życiu dwie usługi językowe TypeScript, niezależnie od tego, czy ich potrzebowała, czy nie, a każda z nich utrzymywała około 95 MB po skompilowaniu czegokolwiek. Są one teraz zbudowane tylko na pierwszej kompilacji, a deklaracje globalnych skryptów JavaScript są przechowywane w obiekcie skryptu w taki sam sposób, w jaki były już skompilowane źródła TypeScript - więc ponowne uruchomienie ich nie regeneruje. To, co tworzy usługa językowa, zostaje ponownie wydana minutę po ostatniej kompilacji i odbudowana na żądanie. W systemie testowym zajęło to instancję od 241 MB do 127 MB sterty (352 MB do 233 MB RSS) (#2373)\nPomocnicy, których edytor skryptów rysuje samodzielnie - wiersz „Wyjaśnij/ Refactor/Test” nad każdą funkcją, podpowiedzi dla identyfikatorów obiektów i wyrażeń CRON oraz sugestie kodu wbudowanego - można wyłączyć. Ustawienie instancji „Pokaż pomocników AI w edytorze skryptów” (ustawienia AI) robi to; jest domyślnie włączone, więc nic się nie zmienia dla każdego, kto jest z nich zadowolony. `Alt+I` nadal pokazuje wartość identyfikatora obiektu pod kursorem, gdy są wyłączone\nRozumowanie punktu końcowego zgodnego z OpenAI zostało wyłączone bezwarunkowo: `rationing_esforç: „none\"` wychodziło z każdym żądaniem, gdy tylko skonfigurowano niestandardowy bazowy adres URL. Jest to właściwe dla małego modelu lokalnego i złe dla wszystkiego innego - za proxy wyłącza rozumowanie samego modelu, za który się płaci lub jest odrzucony. Jest to ustawienie teraz („Wysiłek rozumowania”), a domyślny parametr pozostawia poza nim i pozwala punktowi końcowi decydować\nEdytor AI powiedział adapterowi, jak długo chce czekać, a adapter nigdy go nie odczytał: zablokowane ukończenie w linii utrzymywało jego gniazdo przez pełne dziesięć minut zamiast piętnaście sekund, o które prosił\nUkończenie wbudowane obejmowało model wybrany na czacie AI, ale wybrało samego dostawcę, więc model jednego dostawcy można było zażądać z poświadczeniami i w punkcie końcowym innego. Model i dostawca są teraz zapamiętywane i używane razem\nKiedy dwóch dostawców oferuje model o tej samej nazwie - na przykład proxy i sprzedawca, który za nim stoi - który z nich obsługiwał, decyduje kto z nich odpowiedział jako pierwszy i może zmienić się z jednego przeładowania na następne. Dostawca skonfigurowany jako pierwszy wygrywa teraz, więc bezpośrednia trasa jest preferowana niż proxy",
|
|
131
|
-
"uk": "Правила: порожня смуга «і» складається до свого заголовка. Правило без умов виконує свої дії на кожному тригері, але ця смуга все ще була найвищою річчю в правилі - область падіння з підлогою 64 пікселів, селектор «просто перевірити» та рядок «або» на групу, 292px даремно. Зараз він 41 піксель і говорить «без умови», натискання заголовка знову відкриває його, перетягування умови відкриває його сама, а смуга, яка має умови, ніколи не згортається\nПравила: блокова палітра займає половину кімнати, яку вона зробила. Запис містив 24 пікселі підкладки навколо піктограми 30 пікселів, яка залишила 66 пікселів бічної панелі для одного рядка тексту - тому чотири блоки заповнювали всю висоту, а все інше було за смугою прокрутки. Тепер записи знаходяться на відстані 31 пікселів один від одного, вкладки, що містять лише піктограми над ними, більше не резервують висоту мітки, яку вони не мають, а бічна панель має ширину 168 пікселів замість 200 пікселів. Назва, занадто довга для цього, отримує повний текст як підказку. Кнопка, яка складається палітру, також знаходиться на лінії палітри тепер замість одного пікселя зліва від неї, де вона висіла над краєм вікна, коли палітра була складена\nПравила: вибір стану тригера знизив редактор з «n.replace не є функцією», коли умова стану рядка ще не ввела значення. Вибір стану повторно компілює все правило, і порожнє значення прийшло до порівняння як булеве `false`. Умова без значення тепер порівнюється з порожнім текстом, а число, введене для стану, який є рядком, використовується як його текст\nТепер редактор сценаріїв повідомляє адаптеру кожні 10 секунд, що він відкритий, а адаптер зберігає визначення типів та компілятор гарячими, поки це так, тому збереження сценарію не чекає їх повторного створення. Через 30 секунд після останньої ознаки життя графічний інтерфейс вважається минулим, і все повертається - близько 100 Мб. Вкладка у фоновому режимі не вважається відкритою, тому забута вкладка браузера не може зберегти пам'ять живою протягом кількох днів (#2373)\nВизначення типів Node.js, IObroker та налаштованих бібліотек читалися при кожному запуску, незалежно від того, хотілося б щось їх чи ні. Виконуються лише дві речі - компіляція сценарію TypeScript та вбудований редактор - і вони додають близько 90 Мб до компілятора, тому тепер вони читаються, коли хтось із них насправді запитає. Екземпляр, який виконує простий JavaScript і редагується в іншому місці (дзеркальний каталог, зовнішній редактор), ніколи не читає їх; оголошення глобальних JavaScript генеруються без них і виходять однаковими. Їх також можна вимкнути назавжди («Визначення типів завантаження», вкладка TypeScript) - редактор потім втрачає автодоповнення, і сценарії TypeScript більше не компілюються, про що адаптер попереджає в журналі (#2373)\nКожен екземпляр підтримував дві мовні служби TypeScript живими незалежно від того, потрібні вони їм чи ні, і кожна з них зберігала близько 95 МБ після того, як вона щось зібрав. Тепер вони побудовані лише на першій компіляції, а оголошення глобальних JavaScripts зберігаються на об'єкті сценарію так само, як вже були скомпільовані джерела TypeScript - тому перезапуск більше не відновлює їх. Те, що в кінцевому підсумку створює мовна служба, знову випускається через хвилину після останньої компіляції та перебудовується на вимогу. У тестовій системі це зайняло екземпляр від 241 МБ до 127 МБ купи (352 МБ до 233 МБ RSS) (#2373)\nДопомічники, які редактор сценаріїв малює самостійно - рядок «Explicate/Refactor/Test» над кожною функцією, підказки для ідентифікаторів об'єктів та виразів CRON та вбудовані пропозиції коду - можна вимкнути. Налаштування екземпляра «Показати помічників AI в редакторі сценаріїв» (налаштування AI) робить це; він увімкнений за замовчуванням, тому нічого не змінюється для тих, хто задоволений ними. `Alt+I` все ще показує значення ідентифікатора об'єкта під курсором, коли вони вимкнені\nМіркування кінцевої точки, сумісної з OpenAI, було вимкнено беззастережно: `ing_efort: «none\"` виходило з кожним запитом, як тільки було налаштовано спеціальну базову URL-адресу. Це правильно для невеликої локальної моделі і неправильно для всього іншого - за проксі він відключає міркування тієї самої моделі, за яку платить, або відхиляється. Зараз це налаштування («Зусилля міркування»), і за замовчуванням залишає параметр поза увагою і дозволяє кінцевій точці вирішити\nРедактор AI розповів адаптеру, як довго він готовий чекати, і адаптер ніколи не читав його: застрягла вбудована комплектація тримала свій слот протягом цілих десяти хвилин замість п'ятнадцяти секунд, які він просив\nВбудоване завершення взяло модель, обрану в чаті AI, але вибрало самого провайдера, тому модель одного постачальника можна було запросити з обліковими даними та в кінцевій точці іншого. Модель та постачальник тепер запам'ятовуються та використовуються разом\nКоли два постачальники пропонують однойменну модель - наприклад, проксі та постачальник, який стоїть за нею, - хто з них обслуговував, це вирішувалось тим, хто відповідав першим, і він може змінюватися від одного перезавантаження до іншого. Постачальник, налаштований першим, виграє зараз, тому прямий маршрут є кращим перед проксі-сервером",
|
|
132
|
-
"zh-cn": "规则:空的 “和” 波段向下折叠到其标题。没有条件的规则会在每个触发器上运行,但是该波段仍然是规则中最高的东西——下拉区域的下限为 64 像素,“只需勾选” 选择器以及每组一个 “或” 行,292px 一无所获。现在是 41px,上面写着 “无条件”,点击标题再次将其打开,将条件拖到标题上方会自行打开,其中有条件的波段永远不会折叠\n规则:方块调色板占用的空间是其空间的一半。一个条目在 30 像素的图标周围有 24 像素的边距,为一行文本留下 66 像素的侧边栏——因此四个方块占据了整个高度,其他所有内容都在滚动条后面。现在,条目相隔 31 像素,上方的纯图标选项卡不再保留它们没有的标签的高度,侧边栏的宽度是 168 像素,而不是 200 像素。如果名称太长,则以全文作为其工具提示。折叠调色板的按钮现在也位于调色板的线条上,而不是调色板左边的一个像素,调色板折叠后它就会悬挂在窗口边缘\n规则:当字符串状态的条件尚未输入任何值时,选择触发器的状态会使编辑器关闭,并显示 “n.replace 不是函数”。选择状态会再次编译整个规则,空值作为布尔值 “false” 得出。现在,没有值的条件与空文本进行比较,并且将为状态输入的字符串数字用作其文本\n现在,脚本编辑器每 10 秒告诉适配器它已打开,在这种情况下,适配器会保持类型定义和编译器处于高温状态,因此保存脚本不会等待它们再次构建。在最后一个生命迹象 30 秒后,GUI 算作消失,所有内容都返还了——大约 100 MB。后台的选项卡不算作已打开,因此被遗忘的浏览器选项卡无法使内存存活数天 (#2373)\n无论是否需要它们,每次启动时都会读取 Node.js、IOBroker 和配置库的类型定义。只有两件事能做——编译 TypeScript 脚本和内置编辑器——它们会为编译器增加大约 90 MB,所以现在当其中一个实际提出要求时,它们就会被读取。运行纯 JavaScript 并在其他地方(镜像目录、外部编辑器)编辑的实例永远不会读取它们;全局 JavaScript 的声明是在没有它们的情况下生成的,输出结果相同。它们也可以永久关闭(“加载类型定义”,TypeScript 选项卡)-然后编辑器会丢失自动完成功能,TypeScript 脚本将无法编译,适配器会在日志中警告这一点 (#2373)\n无论是否需要,每个实例都使两个 TypeScript 语言服务处于活动状态,并且每个实例在编译完任何内容后都会保持大约 95 MB 的容量。它们现在仅建立在第一次编译的基础上,并且全局 JavaScript 的声明存储在脚本对象上,就像编译的 TypeScript 源代码一样,因此重启不会再重新生成它们。语言服务最终构建的内容会在上次编译一分钟后再次发布,并按需重建。在测试系统上,这需要一个从 241 MB 到 127 MB 堆的实例(352 MB 到 233 MB RSS)(#2373)\n脚本编辑器自行绘制的帮助程序——每个函数上方的 “解释/重构/测试” 行、对象 ID 和 CRON 表达式的工具提示以及行内代码建议——可以关闭。实例设置 “在脚本编辑器中显示 AI 助手”(AI 设置)可以做到这一点;它默认处于启用状态,因此任何对它们感到满意的人都不会发生任何变化。当光标关闭时,`Alt+I`仍然在光标下方显示对象 ID 的值\n与OpenAI兼容的终端节点的理由被无条件地关闭了:配置了自定义基础网址后,`reasoning_effort: “无” `即取消了每个请求。这对于小型本地模型来说是对的,对其他所有模式来说都是错误的——在代理服务器的背后,它会掩盖人们为之付出代价的理由,或者被拒绝。现在它是一个设置(“推理工作”),默认设置将参数排除在外,让端点决定\nAI 编辑告诉适配器愿意等待多长时间,但适配器从未读过它:嵌入式完成卡住了整整十分钟,而不是要求的十五秒\n内联完成采用了在 AI 聊天中选择的模型,但选择了提供商本身,因此可以使用证书在另一个提供商的端点请求一个提供商的模型。模型和提供商现已被记住并一起使用\n当两个提供商提供同名模型时(例如代理及其背后的供应商),则由最先回答的人决定,并且可以从一次重新加载更改为下一次重新加载。首先配置的提供商现在获胜,因此直接路由优先于代理"
|
|
133
133
|
}
|
|
134
134
|
},
|
|
135
135
|
"platform": "Javascript/Node.js",
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
},
|
|
187
187
|
"dependencies": [
|
|
188
188
|
{
|
|
189
|
-
"js-controller": ">=7.2.
|
|
189
|
+
"js-controller": ">=7.2.5"
|
|
190
190
|
}
|
|
191
191
|
],
|
|
192
192
|
"globalDependencies": [
|
|
@@ -548,6 +548,8 @@
|
|
|
548
548
|
"gptBaseUrl": "",
|
|
549
549
|
"gptBaseUrlKey": "",
|
|
550
550
|
"aiReasoningEffort": "",
|
|
551
|
+
"aiMaxTokens": 8192,
|
|
552
|
+
"historyVersions": 30,
|
|
551
553
|
"aiEditorHelpers": true,
|
|
552
554
|
"claudeKey": "",
|
|
553
555
|
"geminiKey": "",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.javascript",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.4.1",
|
|
4
4
|
"description": "Rules Engine for ioBroker",
|
|
5
5
|
"author": "bluefox <dogafox@gmail.com>",
|
|
6
6
|
"contributors": [
|
|
@@ -42,15 +42,16 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@iobroker/adapter-core": "^3.4.3",
|
|
45
|
-
"@iobroker/
|
|
46
|
-
"@types
|
|
45
|
+
"@iobroker/ai-core": "^0.0.3",
|
|
46
|
+
"@iobroker/types": "^7.2.4",
|
|
47
|
+
"@types/node": "^22.20.5",
|
|
47
48
|
"axios": "^1.20.0",
|
|
48
49
|
"jsonata": "^2.2.2",
|
|
49
50
|
"jszip": "^3.10.2",
|
|
50
51
|
"node-inspect": "^2.0.0",
|
|
51
52
|
"node-schedule": "2.1.1",
|
|
52
|
-
"nodemailer": "^10.0.
|
|
53
|
-
"prettier": "^3.9.
|
|
53
|
+
"nodemailer": "^10.0.14",
|
|
54
|
+
"prettier": "^3.9.9",
|
|
54
55
|
"semver": "^7.8.5",
|
|
55
56
|
"suncalc2": "^1.8.1",
|
|
56
57
|
"typescript": "~6.0.3",
|
|
@@ -65,14 +66,14 @@
|
|
|
65
66
|
"@iobroker/build-tools": "^3.0.3",
|
|
66
67
|
"@iobroker/eslint-config": "^2.3.4",
|
|
67
68
|
"@iobroker/plugin-sentry": "^3.2.1",
|
|
68
|
-
"@iobroker/testing": "^6.
|
|
69
|
+
"@iobroker/testing": "^6.3.0",
|
|
69
70
|
"@tsconfig/node22": "^22.0.6",
|
|
70
71
|
"@types/node-schedule": "^2.1.8",
|
|
71
72
|
"@types/nodemailer": "^8.0.2",
|
|
72
73
|
"@types/request": "^2.48.13",
|
|
73
74
|
"@types/suncalc": "^1.9.2",
|
|
74
75
|
"alcalzone-shared": "^5.0.0",
|
|
75
|
-
"jsdom": "^30.1.
|
|
76
|
+
"jsdom": "^30.1.1",
|
|
76
77
|
"timekeeper": "^2.3.1"
|
|
77
78
|
},
|
|
78
79
|
"bugs": {
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import{An as e,Cr as t,Ct as n,En as r,Er as i,Fn as a,Gt as o,Ht as s,Jn as c,Jt as l,Kt as u,Ln as d,Nn as f,Nr as p,On as m,Or as h,Rn as g,Tt as _,Wt as v,Zn as y,br as b,kr as x,m as S,mt as C,nn as w,or as T,qt as E,sr as D,tn as O,vn as k,wt as A,yn as j}from"./_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-NI-3Uv4e.js";import{t as M}from"./Send-Mdo32jMb.js";import{t as N}from"./vite-preload-helper-CaC3yEL3.js";import{c as ee,o as P,s as F}from"./index-CbQlIKB_.js";import{a as I,c as L,d as R,f as z,h as B,i as V,l as te,m as H,n as U,o as W,p as G,r as ne,s as K,t as q,u as J}from"./AiChatService-QKcpW4jQ.js";import{t as Y}from"./blocklyTheme-CGhU3cEO.js";var X=c(T(`path`,{d:`M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m5 11h-4v4h-2v-4H7v-2h4V7h2v4h4z`}),`AddCircleOutlined`),re=c(T(`path`,{d:`M21.99 4c0-1.1-.89-2-1.99-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4zM17 11h-4v4h-2v-4H7V9h4V5h2v4h4z`}),`AddComment`),ie=c(T(`path`,{d:`M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10h5v-2h-5c-4.34 0-8-3.66-8-8s3.66-8 8-8 8 3.66 8 8v1.43c0 .79-.71 1.57-1.5 1.57s-1.5-.78-1.5-1.57V12c0-2.76-2.24-5-5-5s-5 2.24-5 5 2.24 5 5 5c1.38 0 2.64-.56 3.54-1.47.65.89 1.77 1.47 2.96 1.47 1.97 0 3.5-1.6 3.5-3.57V12c0-5.52-4.48-10-10-10m0 13c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3`}),`AlternateEmail`),ae=c(T(`path`,{d:`M9.01 14H2v2h7.01v3L13 15l-3.99-4zm5.98-1v-3H22V8h-7.01V5L11 9z`}),`CompareArrows`),oe=c(T(`path`,{d:`M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4m0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4`}),`Person`),se=c(T(`path`,{d:`M3 10h11v2H3zm0-4h11v2H3zm0 8h7v2H3zm17.59-2.07-4.25 4.24-2.12-2.12-1.41 1.41L16.34 19 22 13.34z`}),`PlaylistAddCheck`),ce=c(T(`path`,{d:`M20 9V7c0-1.1-.9-2-2-2h-3c0-1.66-1.34-3-3-3S9 3.34 9 5H6c-1.1 0-2 .9-2 2v2c-1.66 0-3 1.34-3 3s1.34 3 3 3v4c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-4c1.66 0 3-1.34 3-3s-1.34-3-3-3M7.5 11.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5S9.83 13 9 13s-1.5-.67-1.5-1.5M16 17H8v-2h8zm-1-4c-.83 0-1.5-.67-1.5-1.5S14.17 10 15 10s1.5.67 1.5 1.5S15.83 13 15 13`}),`SmartToy`);p();var le=[{type:`function`,function:{name:`search_datapoints`,description:`Search ALL ioBroker objects by ID, name, or role — includes states, channels, devices, folders, enums (rooms/functions), adapters, instances, scripts, meta, etc. Returns matching IDs with object type, name, role, unit, and a hasChildren hint for containers. IMPORTANT: Aliases and physical device groupings are usually CHANNELS containing multiple state children (e.g. a motion sensor is often a channel alias.0.Floor.Room.MotionSensor with states ACTUAL, BATTERY, STATE under it). If a channel/device/folder matches your query, call get_object_info on its ID to list its state children. Role-based queries work too: "sensor.motion", "switch.light", "value.temperature".`,parameters:{type:`object`,properties:{query:{type:`string`,description:`Search pattern (case-insensitive substring) - matches against object ID, name, and role. Examples: "bewegungsmelder", "temperature", "sensor.motion", "alias.0", "küche", "zigbee2mqtt.0.lamp".`},max_results:{type:`number`,description:`Maximum number of results to return (default: 20).`},object_type:{type:`string`,description:`Optional filter by object type: "state", "channel", "device", "folder", "enum", "adapter", "instance", "script", "meta", etc. Omit to search every type.`}},required:[`query`]}}},{type:`function`,function:{name:`get_state_value`,description:`Get the current value of an ioBroker state/datapoint. Returns value, timestamp, and acknowledgment flag.`,parameters:{type:`object`,properties:{id:{type:`string`,description:`The full state ID, e.g. "zigbee2mqtt.0.sensor.temperature"`}},required:[`id`]}}},{type:`function`,function:{name:`get_object_info`,description:`Get detailed info about ANY ioBroker object + its full parent hierarchy + direct children. Works for every object type: state, channel, device, folder, adapter, instance, enum, meta, script. Returns: the object itself, parent chain (all non-state ancestors up to the adapter), and — if the object is a container (channel/device/folder/enum/instance/adapter/meta) — the list of direct children with their types, names, roles and units. Use this to navigate the object tree: start from a channel found by search_datapoints, read its children to see the actual state IDs underneath.`,parameters:{type:`object`,properties:{id:{type:`string`,description:`The full object ID, e.g. "zigbee2mqtt.0.0x1234.state", "alias.0.Room.MotionSensor", or "enum.rooms.kitchen".`}},required:[`id`]}}},{type:`function`,function:{name:`search_scripts`,description:`Search through all ioBroker JavaScript/Blockly/Rules scripts. Can search by script name/path OR by content (e.g. find all scripts that use a specific datapoint ID). Returns matching script names, paths, and matching lines.`,parameters:{type:`object`,properties:{query:{type:`string`,description:`Search term - matches against script name, path, AND source code content. Examples: "carport", "zigbee2mqtt.0.lamp.state", "telegram"`},max_results:{type:`number`,description:`Maximum number of scripts to return (default: 10)`}},required:[`query`]}}},{type:`function`,function:{name:`read_script`,description:`Read the full source code of a specific ioBroker script by its ID or path. Use search_scripts first to find the script ID, then read_script to see its complete code.`,parameters:{type:`object`,properties:{id:{type:`string`,description:`The script ID (e.g. "script.js.common.Licht.Carport") or path (e.g. "common/Licht/Carport")`}},required:[`id`]}}},{type:`function`,function:{name:`list_scripts`,description:`List ALL available ioBroker scripts with their names, paths, types (JavaScript/Blockly/TypeScript), and enabled status. Use this to get an overview of all scripts before searching or reading specific ones.`,parameters:{type:`object`,properties:{}}}},{type:`function`,function:{name:`run_script`,description:"Execute a JavaScript or TypeScript snippet in the live ioBroker javascript engine and get back everything it logged. The code runs with the full script API (log, console.*, setState, getState, on, schedule, $, exec, httpGet, …) in VERBOSE mode, so internal operations (setState/getState/subscribe/…) are logged too — ideal for diagnosing behaviour or inspecting values. The snippet runs for a short window and is then automatically STOPPED and fully cleaned up (timers, subscriptions, schedules removed); it does NOT create a persistent script. Use `log(...)` or `console.log(...)` in the code to surface the values you want to inspect. WARNING: side effects are real (e.g. setState changes actual devices) — prefer read-only diagnostics unless the user explicitly asked to change something.",parameters:{type:`object`,properties:{source:{type:`string`,description:`The JavaScript (or TypeScript) source to execute. Log the values you want to inspect via log(...) / console.log(...). Top-level await is supported.`},engineType:{type:`string`,description:`Optional. "TypeScript/ts" to run the code as TypeScript. Defaults to JavaScript.`},timeout:{type:`number`,description:`Optional. Milliseconds to keep the script alive to collect asynchronous logs before it is stopped (default 5000, max 60000). Increase when waiting for timers, subscriptions or HTTP responses.`},logLevel:{type:`string`,description:`Optional minimum severity to return: silly, debug, info, warn, error. Default silly (everything).`}},required:[`source`]}}},{type:`function`,function:{name:`get_editor_selection`,description:`Read what the user has currently selected in the script editor. Returns the selected text and its line/column range, or a message if nothing is selected. Use this when the user refers to "this", "das hier", "the selection", or asks about a specific piece of code they highlighted.`,parameters:{type:`object`,properties:{}}}},{type:`function`,function:{name:`get_editor_content`,description:`Read the full current content of the script editor (may differ from the initial script version if the user has made edits). Use this when you need the live editor state rather than the saved script.`,parameters:{type:`object`,properties:{}}}},{type:`function`,function:{name:`get_cursor_position`,description:`Read the current cursor position (line and column, 1-based) in the script editor.`,parameters:{type:`object`,properties:{}}}},{type:`function`,function:{name:`highlight_text_in_editor`,description:`Search for a literal text in the script editor and select + scroll to it. Returns how many occurrences were found. Use this to draw the user's attention to a specific snippet you are discussing.`,parameters:{type:`object`,properties:{text:{type:`string`,description:`Exact substring to search for (case-sensitive).`}},required:[`text`]}}},{type:`function`,function:{name:`highlight_line_range`,description:`Select and scroll to a range of lines in the editor. Both line numbers are 1-based and inclusive. Use this to show the user which block of code you are referring to.`,parameters:{type:`object`,properties:{start_line:{type:`number`,description:`First line (1-based, inclusive).`},end_line:{type:`number`,description:`Last line (1-based, inclusive).`}},required:[`start_line`,`end_line`]}}},{type:`function`,function:{name:`go_to_line`,description:`Move the cursor to a specific line (and optional column) and scroll that line into view. Use this to navigate the user to a relevant spot.`,parameters:{type:`object`,properties:{line:{type:`number`,description:`1-based line number.`},column:{type:`number`,description:`1-based column (optional, default 1).`}},required:[`line`]}}},{type:`function`,function:{name:`insert_text_at_cursor`,description:`Insert text at the current cursor position in the editor (or replace the current selection if one exists). Use sparingly — prefer returning code in a fenced markdown block so the user can review and smart-apply it. Only use direct insertion when the user explicitly asked you to write something into the editor.`,parameters:{type:`object`,properties:{text:{type:`string`,description:`Text to insert.`}},required:[`text`]}}},{type:`function`,function:{name:`replace_selection`,description:`Replace the currently selected text in the editor with new text. Fails if nothing is selected. Use this to refactor or rewrite a specific highlighted snippet.`,parameters:{type:`object`,properties:{text:{type:`string`,description:`Replacement text.`}},required:[`text`]}}},{type:`function`,function:{name:`get_diagnostics`,description:`Read all active Monaco diagnostics (errors, warnings, info, hints) from the current editor model — this is what shows up as red/yellow squiggles. Use this to find syntax errors, unused variables, missing types, or other editor-reported issues the user might be asking about.`,parameters:{type:`object`,properties:{}}}},{type:`function`,function:{name:`get_document_symbols`,description:`Get the document outline of the current script: all top-level functions, classes, constants, and variables with their line numbers. Use this to understand the structure of a long script or to find where a specific function is defined.`,parameters:{type:`object`,properties:{}}}}];function Z(e){return e&&typeof e==`object`?e.en||e.de||``:e||``}function ue(e,t,n){let r=(n||``).toLowerCase();if(!r)return!1;if(e.toLowerCase().includes(r))return!0;let i=t==null?void 0:t.common;if(!i)return!1;let a=Z(i.name).toLowerCase();if(a&&a.includes(r))return!0;let o=(i.role||``).toLowerCase();return!!(o&&o.includes(r))}async function de(e,t,n=20,r){let i=await I(e),a=r==null?void 0:r.toLowerCase(),o=[],s=Object.keys(i),c=new Set;for(let e of s){let t=e.lastIndexOf(`.`);t>0&&c.add(e.substring(0,t))}for(let e of s){let r=i[e],s=r==null?void 0:r.type;if(!s||a&&s!==a||!ue(e,r,t))continue;let l=r.common,u={id:e,type:s,name:Z(l==null?void 0:l.name)};if(l!=null&&l.role&&(u.role=l.role),s===`state`?(u.stateType=(l==null?void 0:l.type)||``,l!=null&&l.unit&&(u.unit=l.unit)):c.has(e)&&(u.hasChildren=!0),o.push(u),o.length>=n)break}return o.length===0?JSON.stringify({message:`No objects found matching "${t}". Hint: try a role like "sensor.motion" or a partial path.`}):JSON.stringify(o)}async function fe(e,t){try{let n=await e.getState(t);return JSON.stringify(n?{val:n.val,ts:n.ts?new Date(n.ts).toISOString():null,ack:n.ack,from:n.from}:{error:`State '${t}' not found`})}catch{return JSON.stringify({error:`Failed to read state '${t}'`})}}var pe=new Set([`channel`,`device`,`folder`,`adapter`,`instance`,`enum`,`meta`]),me=50;async function he(e,t){try{let r=await e.getObject(t);if(!r)return JSON.stringify({error:`Object '${t}' not found`});let i={id:r._id,type:r.type,common:r.common},a=t.split(`.`),o=[];for(let t=a.length-1;t>=2;t--){let r=a.slice(0,t).join(`.`);try{let t=await e.getObject(r);if(t&&t.type!==`state`){var n;o.push({id:t._id,type:t.type,name:Z((n=t.common)==null?void 0:n.name),common:t.common})}}catch{}}if(o.length>0&&(i.parents=o),pe.has(r.type)){let n=await I(e),r=[],a=`${t}.`,o=!1;for(let e of Object.keys(n))if(e.startsWith(a)&&!e.substring(a.length).includes(`.`)){let t=n[e],i=t==null?void 0:t.common,a={id:e,name:Z(i==null?void 0:i.name),type:(t==null?void 0:t.type)||``};if(i!=null&&i.role&&(a.role=i.role),(t==null?void 0:t.type)===`state`&&i!=null&&i.unit&&(a.unit=i.unit),r.push(a),r.length>=me){o=!0;break}}r.length>0&&(i.children=r,o&&(i.childrenTruncated=!0,i.childrenHint=`Only the first ${me} children are shown. Use search_datapoints with a more specific query or the object_type filter to narrow down.`))}return JSON.stringify(i)}catch{return JSON.stringify({error:`Failed to read object '${t}'`})}}function ge(e){return F(e)||e}function _e(e,t,n=10){let r=t.toLowerCase(),i=[];for(let t of e){let e=t.id.toLowerCase(),a=t.name.toLowerCase(),o=t.id.replace(/^script\.js\./,``).replace(/\./g,`/`),s=t.engineType===`Blockly`||t.engineType===`Rules`,c=e.includes(r)||a.includes(r),l=s?ge(t.source):t.source,u=l.toLowerCase().includes(r);if(c||u){let e={id:t.id,path:o,name:t.name,type:s?`Blockly`:t.engineType.includes(`TypeScript`)?`TypeScript`:`JavaScript`,enabled:t.enabled};if(u){let t=l.split(`
|
|
2
|
-
`),n=[];for(let e=0;e<t.length&&!(t[e].toLowerCase().includes(r)&&(n.push({line:e+1,text:t[e].trim()}),n.length>=5));e++);n.length>0&&(e.matchingLines=n)}if(i.push(e),i.length>=n)break}}return i.length===0?JSON.stringify({message:`No scripts found matching "${t}"`}):JSON.stringify(i)}function ve(e,t){let n=t.replace(/\//g,`.`).toLowerCase(),r=e.find(e=>{let t=e.id.toLowerCase();return t===n||t===`script.js.${n}`||t.endsWith(`.${n}`)});if(!r)return JSON.stringify({error:`Script '${t}' not found. Use search_scripts to find available scripts.`});let i=r.engineType===`Blockly`||r.engineType===`Rules`,a=i?ge(r.source):r.source,o=r.id.replace(/^script\.js\./,``).replace(/\./g,`/`);return JSON.stringify({id:r.id,path:o,name:r.name,type:i?`Blockly`:r.engineType.includes(`TypeScript`)?`TypeScript`:`JavaScript`,enabled:r.enabled,source:a})}function ye(e){let t=e.map(e=>({id:e.id,path:e.id.replace(/^script\.js\./,``).replace(/\./g,`/`),name:e.name,type:e.engineType===`Blockly`||e.engineType===`Rules`?`Blockly`:e.engineType.includes(`TypeScript`)?`TypeScript`:`JavaScript`,enabled:e.enabled}));return JSON.stringify(t)}function Q(){return JSON.stringify({error:`Editor is not available. This tool requires the script editor to be open.`})}async function be(e,t,n){if(!t)return JSON.stringify({error:`No running javascript instance found to execute the script.`});let r=n.source;if(!r||typeof r!=`string`)return JSON.stringify({error:`No source code provided.`});try{var i;let a=await e.sendTo(t,`execute`,{source:r,engineType:n.engineType,timeout:n.timeout,logLevel:n.logLevel});return!a||a.ok===!1?JSON.stringify({error:(a==null?void 0:a.error)||`Execution failed`,logs:(a==null?void 0:a.logs)||[]}):JSON.stringify({engineType:a.engineType,runtime:a.runtime,truncated:a.truncated||!1,logCount:((i=a.logs)==null?void 0:i.length)||0,logs:a.logs||[],output:a.output||``})}catch(e){return JSON.stringify({error:`Failed to execute script: ${e instanceof Error?e.message:String(e)}`})}}async function xe(e,t,n,r,i){let a;try{a=JSON.parse(t.function.arguments)}catch{return JSON.stringify({error:`Invalid arguments: ${t.function.arguments}`})}switch(t.function.name){case`search_datapoints`:return de(e,a.query,a.max_results||20,a.object_type);case`get_state_value`:return fe(e,a.id);case`get_object_info`:return he(e,a.id);case`search_scripts`:return _e(n||[],a.query,a.max_results||10);case`read_script`:return ve(n||[],a.id);case`list_scripts`:return ye(n||[]);case`run_script`:return be(e,i,a);case`get_editor_selection`:{if(!(r!=null&&r.getSelection))return Q();let e=r.getSelection();return JSON.stringify(e||{message:`No text is currently selected in the editor.`})}case`get_editor_content`:return r!=null&&r.getContent?JSON.stringify({content:r.getContent()}):Q();case`get_cursor_position`:{if(!(r!=null&&r.getCursorPosition))return Q();let e=r.getCursorPosition();return JSON.stringify(e||{message:`Editor has no cursor position (not focused).`})}case`highlight_text_in_editor`:{if(!(r!=null&&r.highlightText))return Q();let e=r.highlightText(a.text);return JSON.stringify({matches:e,message:e===0?`Text "${a.text}" was not found in the editor.`:`Highlighted ${e} occurrence(s) of "${a.text}".`})}case`highlight_line_range`:{if(!(r!=null&&r.highlightLineRange))return Q();let e=r.highlightLineRange(a.start_line,a.end_line);return JSON.stringify({success:e,message:e?`Selected lines ${a.start_line}-${a.end_line}.`:`Could not select the requested line range.`})}case`go_to_line`:{if(!(r!=null&&r.goToLine))return Q();let e=r.goToLine(a.line,a.column);return JSON.stringify({success:e,message:e?`Cursor moved to line ${a.line}.`:`Could not move the cursor.`})}case`insert_text_at_cursor`:{if(!(r!=null&&r.insertTextAtCursor))return Q();let e=r.insertTextAtCursor(a.text);return JSON.stringify({success:e,message:e?`Text inserted at cursor.`:`Editor rejected the insertion.`})}case`replace_selection`:{if(!(r!=null&&r.replaceSelection))return Q();let e=r.replaceSelection(a.text);return JSON.stringify({success:e,message:e?`Selection replaced.`:`No text was selected to replace.`})}case`get_diagnostics`:{if(!(r!=null&&r.getDiagnostics))return Q();let e=r.getDiagnostics();return JSON.stringify({count:e.length,diagnostics:e})}case`get_document_symbols`:{if(!(r!=null&&r.getSymbols))return Q();let e=await r.getSymbols();return JSON.stringify({count:e.length,symbols:e})}default:return JSON.stringify({error:`Unknown tool: ${t.function.name}`})}}var Se=0;function Ce(){return`msg_${Date.now()}_${++Se}`}function we(e){let{socket:n,runningInstances:r,currentCode:i,currentLanguage:a,allScripts:o,editorApi:s,currentScriptId:c}=e,l=b((e,t,n)=>e===`none`||!n?null:{range:t,scriptId:c||``,scriptVersion:(i||``).length,kind:e,originalText:n},[c,i]),[u,d]=x(()=>{try{let e=window.localStorage.getItem(`Editor.aiChatMessages`);return e?JSON.parse(e):[]}catch{return[]}}),f=b(e=>{d(t=>{let n=typeof e==`function`?e(t):e,r=n.length>100?n.slice(-100):n;try{window.localStorage.setItem(`Editor.aiChatMessages`,JSON.stringify(r))}catch{try{let e=r.slice(-20);window.localStorage.setItem(`Editor.aiChatMessages`,JSON.stringify(e))}catch{}}return r})},[]),[p,m]=x(!1),[g,_]=x(null),[v,y]=x(window.localStorage.getItem(`Editor.aiChatMode`)||`agent`),C=b(e=>{y(e),window.localStorage.setItem(`Editor.aiChatMode`,e)},[]),[w,T]=x(null),[E,D]=x(window.localStorage.getItem(`openai-model`)||``),[O,k]=x([]),[A,j]=x({}),[M,F]=x(!0),[I,U]=x(null),q=h(null),Y=h(null),X=h(null),re=h(null),ie=b(e=>{D(e),G(e,A[e])},[A]),ae=b(async()=>{F(!0),U(null);try{let e=await R(n,r);if(k(e.models),j(e.providerMap),e.models.length>0){let t=z().model,n=t&&e.models.includes(t)?t:e.models[0];D(n),G(n,e.providerMap[n])}e.errors.length>0&&U(e.errors.join(`; `))}catch(e){U(String(e))}F(!1)},[n,r]);t(()=>{ae()},[ae]);let oe=b(e=>{let t=!1,n=!1,r=[],i=!1,a=/@([\w/äöüÄÖÜß-]+)/g,s;for(;(s=a.exec(e))!==null;){let e=s[1].toLowerCase();if(e===`alle`||e===`all`)t=!0;else if(e===`geräte`||e===`devices`||e===`geraete`)n=!0;else if(i=!0,o&&o.length>0){let e=s[1].replace(/\//g,`.`).toLowerCase(),t=e.split(`.`),n=o.find(n=>{let r=n.id.toLowerCase(),i=r.replace(/^script\.js\./,``);if(i===e||i.endsWith(`.${e}`)||r===`script.js.${e}`)return!0;let a=0;for(let e of t){let t=i.indexOf(e,a);if(t===-1)return!1;a=t+e.length}return!0});if(n)r.push(n.id);else for(let e of t){if(e.length<3)continue;let t=o.filter(t=>t.id.toLowerCase().includes(`.${e}`)||t.name.toLowerCase().includes(e));for(let e of t)r.includes(e.id)||r.push(e.id)}}}return i&&r.length===0&&(t=!0),{cleanMessage:e.replace(/@[\w/äöüÄÖÜß]+\s*/g,``).trim(),mentionedScriptIds:r,includeAll:t,includeDevices:n}},[o]),se=b(async(e,t,s)=>{re.current||=await te(),q.current||=await W(n,r);let c=J(),l=a===`blockly`,u=e||s.length>0,d=`You are an AI assistant for ioBroker JavaScript adapter scripting. Help the user write, debug, and understand ioBroker scripts. Write comments in ${c}. Use the ioBroker JavaScript API correctly.
|
|
3
|
-
|
|
4
|
-
ioBroker object hierarchy: adapter.instance.device.channel.state
|
|
5
|
-
- A "state" is a single datapoint (e.g. zigbee2mqtt.0.0x1234.temperature)
|
|
6
|
-
- A "channel" groups related states (e.g. zigbee2mqtt.0.0x1234 contains temperature, humidity, battery)
|
|
7
|
-
- A "device" groups channels (e.g. zigbee2mqtt.0.0x1234)
|
|
8
|
-
- The channel/device often has the human-readable name (e.g. "Living Room Sensor")
|
|
9
|
-
When looking up info about a datapoint, ALWAYS also check its parent channel/device for the device name and context. Use get_object_info which returns the full parent hierarchy automatically.
|
|
10
|
-
|
|
11
|
-
To verify code or diagnose runtime behaviour, you can use the run_script tool: it executes a JavaScript/TypeScript snippet in the live engine (verbose mode) and returns everything it logged, then auto-stops it. Log the values you want to inspect via log(...) / console.log(...). It runs against the live system, so prefer read-only diagnostics (getState, $, getObject) and only call setState when the user explicitly asked to change something.
|
|
12
|
-
|
|
13
|
-
Available API and syntax rules:
|
|
14
|
-
${re.current}`;if(l&&(d+="\n\nThe user is working in the Blockly visual editor. When asked to create or modify code, respond with Blockly XML in a ```xml code block instead of JavaScript."),(t||e)&&(X.current||=await V(n),d+=`\n\nAvailable smart home devices:\n${JSON.stringify(X.current,null,0)}`),!u&&i){if(l){let e=i.indexOf(`%%BLOCKLY_XML%%`),t=e===-1?i:i.substring(0,e).trim(),n=e===-1?``:i.substring(e+15).trim();d+=`\n\nThe user is working on this Blockly script (currently open in the editor).\n\nGenerated JavaScript (shows the logic):\n\`\`\`javascript\n${t}\n\`\`\``,n&&(d+=`\n\nBlockly XML (use for modifications):\n\`\`\`xml\n${n}\n\`\`\``)}else d+=`\n\nThe user's question is about this script (currently open in the editor, ${a||`javascript`}):\n\`\`\`${a||`javascript`}\n${i}\n\`\`\``}if(e&&o&&o.length>0)d+=`\n\nThe user requested ALL scripts. Search through all of them to answer the question. Always identify WHICH script you describe by its full ID. Scripts may reference datapoint IDs via variables.\n\n${P(o,!0)}`;else if(s.length>0&&o){let e=o.filter(e=>s.includes(e.id));e.length>0&&(d+=`\n\nIMPORTANT: The user is asking about the following script(s). Answer ONLY about these scripts, NOT about the currently open editor tab. Analyze the source code below carefully:\n\n${P(e,!0)}`)}return l&&(d+=`\n\n${K(c)}`),[{role:`system`,content:d}]},[n,r,i,a,o]),ce=b(async e=>{if(!e.trim()||p)return;let t=A[E];if(!t){T(S.t(`Please select a valid model`));return}let i=q.current||await W(n,r);if(q.current=i,!i){T(S.t(`No API keys configured`));return}let o=Object.keys(r)[0];if(!o){T(S.t(`No running javascript instance found`));return}let s=t===`custom`&&i.gptBaseUrl||``,c={id:Ce(),role:`user`,content:e,timestamp:Date.now()},l={id:Ce(),role:`assistant`,content:`⏳ ${S.t(`Generating plan...`)}`,timestamp:Date.now()};f(e=>[...e,c,l]),m(!0),T(null);try{let r=J();X.current||=await V(n);let i=X.current||[],c=`Devices in my smart home:\n${JSON.stringify(i)}\n\nI need a plan for this task: ${e}\n\nAnswer with max 6 lines. Use FULL device IDs from the list above (e.g. zigbee2mqtt.0.0xa4c1383f5ef5fb07.state). No explanation. No reasoning.\n1. IDs: <full IDs from the device list. If a device is not in the list, use TODO_DEVICE_ID as placeholder>\n2. Trigger: <on(id) for state changes OR schedule('min hour * * *') for time-based tasks>\n3. Condition: <when to act>\n4. Actions: <what to set, with full IDs and values. For Telegram use sendTo('telegram.0', 'send', {text: msg})>\n5. Else: <alternative actions or nothing>\n6. Extra: <logging, formatting, etc.>\nValues are boolean (true/false) or numbers, not strings. Use .state not .state_toggle.`,l=await H(n,o,{messages:[{role:`user`,content:c}],model:E,provider:t,baseUrl:s});if(l.error){T(l.error),f(e=>e.slice(0,-2)),m(!1);return}let u=B(l.content||``);f(e=>{let t=[...e],n=t[t.length-1];return(n==null?void 0:n.role)===`assistant`&&(t[t.length-1]={...n,content:`📋 **${S.t(`Plan`)}:**\n${u}`}),t});let d={id:Ce(),role:`assistant`,content:`⏳ ${S.t(`Generating code...`)}`,timestamp:Date.now()};f(e=>[...e,d]);let p=a===`blockly`,h=p?`TASK: ${e}\n\nPLAN:\n${u}\n\nGenerate Blockly XML blocks for this ioBroker automation. Use the exact state IDs from the plan. If the plan contains TODO_DEVICE_ID, keep it as a placeholder. Write comments in ${r}. Put the blocks in a \`\`\`xml code block. You may add a short explanation before or after the XML.`:`TASK: ${e}\n\nPLAN:\n${u}\n\nWrite the ioBroker script. Use the exact state IDs from the plan. If the plan contains TODO_DEVICE_ID, keep it as a placeholder with a comment so the user can fill in the correct ID. Write comments in ${r}. Put the code in a \`\`\`javascript code block. You may add a short explanation before or after the code.`,g=p?K(r):L(r),v=await H(n,o,{messages:[{role:`system`,content:g},{role:`user`,content:h}],model:E,provider:t,baseUrl:s});if(v.error){T(v.error),f(e=>e.slice(0,-1)),m(!1);return}let y=B(v.content||``);f(e=>{let t=[...e],n=t[t.length-1];return(n==null?void 0:n.role)===`assistant`&&(t[t.length-1]={...n,content:y}),t}),_(`${S.t(`devices`)}: ${i.length}`)}catch(e){T(String(e)),f(e=>e.slice(0,-1))}m(!1)},[E,A,p,n,r,a,f]),Z=b(async e=>{if(v===`code`)return ce(e);if(!e.trim()||p)return;let t=A[E];if(!t){T(S.t(`Please select a valid model`));return}let i=q.current||await W(n,r);if(q.current=i,!i){T(S.t(`No API keys configured`));return}let a=Object.keys(r)[0];if(!a){T(S.t(`No running javascript instance found`));return}let c=Y.current;if(Y.current=null,!c)try{var d;let e=s==null||(d=s.getSelection)==null?void 0:d.call(s);e&&e.text&&(c=l(`selection`,e.range,e.text))}catch{}let h={id:Ce(),role:`user`,content:e,timestamp:Date.now(),sourceRange:c},g={id:Ce(),role:`assistant`,content:``,timestamp:Date.now(),sourceRange:c};f(e=>[...e,h,g]),m(!0),T(null);let{cleanMessage:y,mentionedScriptIds:b,includeAll:x,includeDevices:C}=oe(e),w=[];if(x)w.push(`${S.t(`all scripts`)} (${(o==null?void 0:o.length)||0})`);else if(b.length>0){let e=b.map(e=>e.replace(/^script\.js\./,``));w.push(e.join(`, `))}else w.push(S.t(`current script`));C&&w.push(S.t(`devices`)),_(`${S.t(`Context`)}: ${w.join(` + `)}`);let D=await se(x,C,b),O=t===`custom`&&i.gptBaseUrl||``,k=y||e;if(o&&o.length>0){let e=k.match(/\b[\w-]+\.\d+\.[\w.-]+/g);if(e){let t=[];for(let n of new Set(e)){let e=ee(o,n);e.length>0&&t.push(`Datapoint "${n}" is used in:\n${e.map(e=>` - ${e.scriptName} (${e.scriptId}) line ${e.lineNumber}: ${e.usageType} → ${e.line}`).join(`
|
|
15
|
-
`)}`)}t.length>0&&(k+=`\n\n[Automatic analysis results]\n${t.join(`
|
|
16
|
-
|
|
17
|
-
`)}`)}}let j=[...D,...u.filter(e=>e.role!==`system`).map(e=>({role:e.role,content:e.content})),{role:`user`,content:k}],M=v===`agent`;try{let e=[...j];for(let r=0;r<5;r++){let i=await H(n,a,{messages:e,model:E,provider:t,baseUrl:O,...M?{tools:le}:{}});if(i.error){if(M&&r===0&&i.error.toLowerCase().includes(`tool`)){let r=await H(n,a,{messages:e,model:E,provider:t,baseUrl:O});if(r.error)T(r.error),f(e=>e.slice(0,-1));else{let e=B(r.content||``);f(t=>{let n=[...t],r=n[n.length-1];return(r==null?void 0:r.role)===`assistant`&&(n[n.length-1]={...r,content:e}),n})}break}T(i.error),f(e=>e.slice(0,-1));break}let c=i.tool_calls;if((!c||c.length===0)&&M&&i.content){let e=i.content.trim();try{let t=JSON.parse(e);t.name&&t.arguments&&(c=[{id:`text_tool_${Date.now()}`,type:`function`,function:{name:t.name,arguments:JSON.stringify(t.arguments)}}])}catch{}}if(!c||c.length===0){let e=B(i.content||``);f(t=>{let n=[...t],r=n[n.length-1];return(r==null?void 0:r.role)===`assistant`&&(n[n.length-1]={...r,content:e}),n});break}i.tool_calls=c;let l=i.tool_calls.map(e=>{let t={};try{t=JSON.parse(e.function.arguments)}catch{}switch(e.function.name){case`search_datapoints`:return`🔍 ${S.t(`Searching datapoints`)}: "${String(t.query||``)}"`;case`get_state_value`:return`📊 ${S.t(`Reading value`)}: ${String(t.id||``)}`;case`get_object_info`:return`📋 ${S.t(`Loading object info`)}: ${String(t.id||``)}`;case`search_scripts`:return`🔍 ${S.t(`Searching scripts`)}: "${String(t.query||``)}"`;case`read_script`:return`📖 ${S.t(`Reading script`)}: ${String(t.id||``)}`;case`list_scripts`:return`📂 ${S.t(`Loading script list`)}`;default:return`⚙️ ${e.function.name}`}});f(e=>{let t=[...e],n=t[t.length-1];return(n==null?void 0:n.role)===`assistant`&&(t[t.length-1]={...n,content:l.join(`
|
|
18
|
-
`)}),t}),e.push({role:`assistant`,content:i.content||``,tool_calls:i.tool_calls});for(let t of i.tool_calls){let r=await xe(n,t,o,s,a);e.push({role:`tool`,tool_call_id:t.id,content:r})}}}catch(e){T(String(e)),f(e=>e.slice(0,-1))}m(!1)},[E,A,u,p,n,r,se,oe,o,v,ce,f,l,s]),ue=b(()=>{f([]),T(null),m(!1),_(null),ne(),window.localStorage.removeItem(`Editor.aiChatHistory`)},[f]),de=b(async(e,t)=>{let i=A[E];if(!i)return`Error: ${S.t(`Please select a valid model`)}`;let o=q.current||await W(n,r);if(q.current=o,!o)return`Error: ${S.t(`No API keys configured`)}`;let s=Object.keys(r)[0];if(!s)return`Error: ${S.t(`No running javascript instance found`)}`;let c=i===`custom`&&o.gptBaseUrl||``,l=a||`javascript`,u=`You are an assistant for writing ioBroker ${l} scripts. The user will ask a question about a snippet of their code. Match your answer to the question: \n- If they ask for an explanation, description, or "what does this do?", reply with clear prose (a few sentences). Do NOT repeat the code unchanged. \n- If they explicitly ask for a change, refactor, fix, or rewrite, reply with a single fenced \`\`\`${l===`blockly`?`xml`:l}\`\`\` code block containing the full replacement for the selection. You may add one short sentence before or after the block. \n- If they ask something ambiguous or meta (e.g. "is this correct?"), reply in prose first and only include code if proposing a change. \nioBroker globals available in scripts: on, setState, getState, schedule, sendTo, log, createState, setStateDelayed, existsState, httpGet, httpPost.`,d=t?`Code from my editor:\n\n\`\`\`${l===`blockly`?`xml`:l}\n${t}\n\`\`\`\n\n${e}`:e;try{let e=await H(n,s,{messages:[{role:`system`,content:u},{role:`user`,content:d}],model:E,provider:i,baseUrl:c});return e.error?`Error: ${e.error}`:e.content||``}catch(e){return`Error: ${e.message||String(e)}`}},[E,A,r,n,a]);return{messages:u,isLoading:p,error:w,model:E,availableModels:O,modelProviderMap:A,modelsLoading:M,modelsError:I,lastContextInfo:g,mode:v,setMode:C,setModel:ie,sendMessage:Z,triggerAiAction:b(e=>{e.range&&e.code?Y.current=l(e.kind||`codelens`,e.range,e.code):Y.current=null,N(async()=>{let{buildActionPrompt:e}=await import(`./aiPromptBuilder-yTB6N2VT.js`);return{buildActionPrompt:e}},[],import.meta.url).then(({buildActionPrompt:t})=>{let n=t({action:e.action,code:e.code,language:a||`javascript`,diagnostic:e.diagnostic,question:e.question,rangeLabel:e.rangeLabel});n?Z(n):Y.current=null}).catch(()=>{Y.current=null,T(S.t(`Failed to build AI action prompt`))})},[Z,a,l]),askInline:de,clearChat:ue,retryLoadModels:ae}}p();var Te=({code:e,language:r,themeType:i,onInsertCode:a,onShowDiff:o,sourceRange:s})=>{let c=h(null);t(()=>{var t;let n=window.monaco;if(!c.current||!(n!=null&&(t=n.editor)!=null&&t.colorize))return;let a=r===`ts`||r===`typescript`?`typescript`:r||`javascript`;n.editor.colorize(e,a,{theme:i===`dark`?`vs-dark`:`vs`}).then(e=>{c.current&&(c.current.innerHTML=e)})},[e,r,i]);let l=b(()=>{navigator.clipboard.writeText(e)},[e]);return D(u,{sx:{position:`relative`,my:1,borderRadius:1,overflow:`hidden`,border:`1px solid`,borderColor:`divider`},children:[D(u,{sx:{display:`flex`,justifyContent:`space-between`,alignItems:`center`,px:1,py:.5,bgcolor:`action.hover`,borderBottom:`1px solid`,borderColor:`divider`},children:[T(u,{sx:{fontSize:`0.75rem`,color:`text.secondary`,textTransform:`uppercase`},children:r||`javascript`}),D(u,{children:[T(v,{title:S.t(`Copy`),children:T(j,{size:`small`,onClick:l,children:T(n,{sx:{fontSize:16}})})}),a&&T(v,{title:S.t(`Insert into editor`),children:T(j,{size:`small`,onClick:()=>a(e),children:T(X,{sx:{fontSize:16}})})}),o&&T(v,{title:S.t(`Show as diff`),children:T(j,{size:`small`,onClick:()=>o(e,s),children:T(ae,{sx:{fontSize:16}})})})]})]}),T(`pre`,{ref:c,style:{margin:0,padding:`8px 12px`,overflow:`auto`,maxHeight:400,fontSize:`13px`,fontFamily:`'Cascadia Code', 'Fira Code', 'Consolas', monospace`,backgroundColor:i===`dark`?`#1e1e1e`:`#f8f8f8`,color:i===`dark`?`#d4d4d4`:`#333`},children:e})]})};p();var Ee=({xml:e})=>{let n=y(),r=h(null),i=h(null),[a,o]=x(60),s=h(!1);return t(()=>{s.current&&(s.current=!1,requestAnimationFrame(()=>{let e=window.Blockly,t=i.current;e&&t&&(e.svgResize(t),t.scrollCenter())}))},[a]),t(()=>{let t=window.Blockly;if(t&&r.current){i.current&&=(i.current.dispose(),null);try{let a=t.inject(r.current,{readOnly:!0,toolbox:null,trashcan:!1,zoom:{controls:!1,wheel:!1,startScale:1},move:{scrollbars:!1,drag:!1,wheel:!1},sounds:!1,renderer:`thrasos`,theme:Y(n),media:`google-blockly/media/`});i.current=a;let c=e.trim();c.startsWith(`<xml`)||(c=`<xml xmlns="https://developers.google.com/blockly/xml">${c}</xml>`);let l=t.utils.xml.textToDom(c),u=10,d=Array.from(l.querySelectorAll(`:scope > block`));for(let e of d)e.setAttribute(`x`,`10`),e.setAttribute(`y`,String(u)),u+=200;t.Xml.domToWorkspace(l,a);let f=a.getTopBlocks(!1);if(f.length>1){let e=10;for(let t of f){let n=t.getRelativeToSurfaceXY();t.moveBy(10-n.x,e-n.y),e+=t.getHeightWidth().height+20}}let p=a.getBlocksBoundingBox();if(p){let e=p.bottom-p.top+20,t=Math.max(60,Math.ceil(e));s.current=!0,o(t)}}catch{}return()=>{i.current&&=(i.current.dispose(),null)}}},[e,n]),T(u,{ref:r,sx:{width:`100%`,height:a,minHeight:60,borderRadius:1,overflow:`hidden`,border:`1px solid`,borderColor:`divider`}})};p();function De(e){let t=[],n=/```(\w*)\n?([\s\S]*?)```/g,r=0,i;for(;(i=n.exec(e))!==null;){if(i.index>r){let n=e.substring(r,i.index).trim();n&&t.push({type:`text`,content:n})}t.push({type:`code`,content:i[2].trim(),language:i[1]||`javascript`}),r=i.index+i[0].length}if(r<e.length){let n=e.substring(r).trim();n&&t.push({type:`text`,content:n})}return t.length===0&&t.push({type:`text`,content:e}),t}function $(e){let t=[],n=/(\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`)/g,r=0,i,a=0;for(;(i=n.exec(e))!==null;)i.index>r&&t.push(e.substring(r,i.index)),i[2]?t.push(T(`strong`,{children:i[2]},a++)):i[3]?t.push(T(`em`,{children:i[3]},a++)):i[4]&&t.push(T(`code`,{className:`ai-chat-inline-code`,style:{padding:`2px 6px`,borderRadius:4,fontSize:`0.85em`,fontFamily:`'Cascadia Code', 'Fira Code', 'Consolas', monospace`},children:i[4]},a++)),r=i.index+i[0].length;return r<e.length&&t.push(e.substring(r)),t}function Oe(e){return e.trim().startsWith(`|`)&&e.trim().endsWith(`|`)}function ke(e){return/^\|[\s:]*-+[\s:|-]*\|$/.test(e.trim())}function Ae(e,t,n){let r=t.palette.mode===`dark`,i=e=>e.trim().replace(/^\||\|$/g,``).split(`|`).map(e=>e.trim()),a=i(e[0]),o=e.slice(2).map(i);return T(u,{sx:{overflowX:`auto`,my:1},children:D(`table`,{style:{borderCollapse:`collapse`,width:`100%`,fontSize:`0.8rem`,color:t.palette.text.primary},children:[T(`thead`,{children:T(`tr`,{children:a.map((e,n)=>T(`th`,{style:{border:`1px solid ${t.palette.divider}`,padding:`6px 10px`,backgroundColor:r?t.palette.grey[800]:t.palette.grey[100],color:t.palette.text.primary,fontWeight:600,textAlign:`left`},children:$(e)},n))})}),T(`tbody`,{children:o.map((e,n)=>T(`tr`,{style:{backgroundColor:n%2==1?r?t.palette.grey[900]:t.palette.grey[50]:void 0},children:e.map((e,n)=>T(`td`,{style:{border:`1px solid ${t.palette.divider}`,padding:`6px 10px`,color:t.palette.text.primary},children:$(e)},n))},n))})]})},n)}function je(e,t){let n=e.split(`
|
|
19
|
-
`),r=[],i=0,a=0;for(;a<n.length;){let e=n[a].trim();if(e===``){a++;continue}if(/^(-{3,}|\*{3,}|_{3,})$/.test(e)){r.push(T(`hr`,{style:{border:`none`,borderTop:`1px solid ${t.palette.divider}`,margin:`8px 0`}},i++)),a++;continue}let o=e.match(/^(#{1,4})\s+(.+)$/);if(o){let e=o[1].length;r.push(T(`div`,{style:{fontWeight:600,fontSize:[`1.2em`,`1.1em`,`1em`,`0.95em`][e-1],margin:`8px 0 4px`},children:$(o[2])},i++)),a++;continue}if(Oe(e)&&a+1<n.length&&ke(n[a+1].trim())&&a+2<n.length){let e=[n[a],n[a+1]],o=a+2;for(;o<n.length&&Oe(n[o]);)e.push(n[o]),o++;r.push(Ae(e,t,i++)),a=o;continue}if(/^[-*+]\s/.test(e)){let e=[];for(;a<n.length&&/^\s*[-*+]\s/.test(n[a]);)e.push(n[a].replace(/^\s*[-*+]\s/,``).trim()),a++;r.push(T(`ul`,{style:{margin:`4px 0`,paddingLeft:20},children:e.map((e,t)=>T(`li`,{children:$(e)},t))},i++));continue}if(/^\d+[.)]\s/.test(e)){let e=[];for(;a<n.length&&/^\s*\d+[.)]\s/.test(n[a]);)e.push(n[a].replace(/^\s*\d+[.)]\s/,``).trim()),a++;r.push(T(`ol`,{style:{margin:`4px 0`,paddingLeft:20},children:e.map((e,t)=>T(`li`,{children:$(e)},t))},i++));continue}r.push(T(`div`,{children:$(e)},i++)),a++}return r}var Me=({message:e,themeType:t,currentLanguage:n,onInsertCode:r,onShowDiff:a,onApplyCode:o})=>{let s=e.role===`user`,c=E(),d=s?t===`dark`?c.palette.primary.dark:c.palette.primary.main:t===`dark`?c.palette.secondary.dark:c.palette.secondary.main,f=c.palette.getContrastText(d),p=i(()=>De(e.content),[e.content]),m=(e,t)=>!!(e===`xml`||e===`blockly`||n===`blockly`&&t&&/<block\s+type=/.test(t));return D(u,{sx:{display:`flex`,gap:1,px:1.5,py:1,mx:.75,my:.5,bgcolor:s?t===`dark`?`rgba(144, 202, 249, 0.10)`:`rgba(25, 118, 210, 0.07)`:t===`dark`?`rgba(206, 147, 216, 0.10)`:`rgba(156, 39, 176, 0.06)`,borderRadius:1.5,borderLeft:`3px solid`,borderLeftColor:d,transition:`background-color 120ms`,"&:hover":{bgcolor:s?t===`dark`?`rgba(144, 202, 249, 0.16)`:`rgba(25, 118, 210, 0.12)`:t===`dark`?`rgba(206, 147, 216, 0.16)`:`rgba(156, 39, 176, 0.10)`}},children:[T(g,{sx:{width:28,height:28,bgcolor:d,color:f,flexShrink:0,mt:.5},children:T(s?oe:ce,{sx:{fontSize:18}})}),T(u,{sx:{flex:1,minWidth:0,fontSize:`0.875rem`,lineHeight:1.6},children:p.map((n,i)=>n.type===`code`?m(n.language,n.content)?D(u,{sx:{my:1},children:[T(Ee,{xml:n.content}),D(u,{sx:{display:`flex`,gap:.5,mt:.5},children:[o&&T(l,{size:`small`,variant:`contained`,color:`primary`,startIcon:T(se,{sx:{fontSize:14}}),onClick:()=>o(n.content),sx:{textTransform:`none`,fontSize:`0.75rem`},children:S.t(`Apply blocks`)}),r&&T(l,{size:`small`,variant:`outlined`,startIcon:T(X,{sx:{fontSize:14}}),onClick:()=>r(n.content),sx:{textTransform:`none`,fontSize:`0.75rem`},children:S.t(`Insert blocks`)})]})]},i):T(Te,{code:n.content,language:n.language||`javascript`,themeType:t,onInsertCode:r,onShowDiff:a,sourceRange:e.sourceRange||null},i):T(u,{sx:{wordBreak:`break-word`,color:c.palette.text.primary},children:je(n.content,c)},i))})]})};function Ne(e){let t=(e||``).toLowerCase();return t.includes(`blockly`)||t.includes(`rules`)?`blockly`:t.includes(`typescript`)?`typescript`:`javascript`}function Pe(e,t){return`\`\`\`${t===`blockly`?`xml`:t}\n${e}\n\`\`\``}function Fe(e){let t=(e.code||``).trim(),n=Ne(e.language),r=e.rangeLabel?` (${e.rangeLabel})`:``;switch(e.action){case`explain`:return t?[`Please explain what this ioBroker ${n} code does${r}.`,`Focus on: which datapoints it reads/writes, which triggers fire it, and any side-effects.`,``,Pe(t,n)].join(`
|
|
20
|
-
`):null;case`refactor`:return t?[`Refactor this ioBroker ${n} code${r} to be cleaner and more idiomatic.`,`Preserve behavior exactly. Keep ioBroker APIs (on, setState, getState, schedule, sendTo, log).`,`Return the full refactored block inside a \`\`\`${n===`blockly`?`xml`:n}\`\`\` code block so it can be smart-applied.`,``,Pe(t,n)].join(`
|
|
21
|
-
`):null;case`comment`:return t?[`Add clear, concise inline comments to this ioBroker ${n} code${r}.`,`Only add comments where they add real value (non-obvious logic, tricky edge cases, business rules).`,`Do not over-comment trivial lines. Return the commented version in a code block.`,``,Pe(t,n)].join(`
|
|
22
|
-
`):null;case`fix`:{if(!t)return null;let i=(e.diagnostic||``).trim();return[`This ioBroker ${n} code has an issue${r}. Please fix it and return the corrected code.${i?`\nReported problem: ${i}`:``}`,`Keep the fix minimal — do not rewrite unrelated parts.`,``,Pe(t,n)].join(`
|
|
23
|
-
`)}case`tests`:return t?[`Suggest how to test this ioBroker ${n} script manually inside the ioBroker admin UI${r}.`,``,"ioBroker scripts run inside the adapter sandbox and CANNOT be unit-tested with Jest, Mocha, or any external test framework. Do NOT propose Jest/Mocha tests, do NOT propose extracting the code into a separate Node.js project, do NOT write `describe` / `test` blocks.",``,`Instead, propose a short list of manual test cases. For each case describe:`,` • Setup — which ioBroker datapoints to prepare and to which values (via the objects tree "Values" tab)`,` • Action — what to trigger: set a state with setState, wait for a schedule, change a sensor value, etc.`,` • Expected — what should happen afterwards: which states should change, what should appear in the adapter log (javascript.0), which side effects are visible`,``,`Keep it concise: 3-6 cases covering the happy path, typical edge cases, and any guard conditions the script has.`,``,Pe(t,n)].join(`
|
|
24
|
-
`):null;case`ask`:{let i=(e.question||``).trim();return i?t?[`Regarding this ioBroker ${n} code${r}:`,``,Pe(t,n),``,i].join(`
|
|
25
|
-
`):i:null}default:return null}}function Ie(e){let t=(e||``).trimStart();if(!t.startsWith(`/`))return null;let n=t.match(/^\/(\w+)(?:\s+([\s\S]*))?$/);if(!n)return null;let r=n[1].toLowerCase(),i=(n[2]||``).trim(),a={explain:`explain`,erklaere:`explain`,erklaeren:`explain`,refactor:`refactor`,refaktor:`refactor`,refaktoriere:`refactor`,comment:`comment`,comments:`comment`,kommentar:`comment`,kommentiere:`comment`,fix:`fix`,fixme:`fix`,tests:`tests`,test:`tests`,ask:`ask`,frag:`ask`,frage:`ask`}[r];return a?{action:a,rest:i}:null}p();function Le(){return[{id:`@all`,label:S.t(`mention @all`),descriptionKey:`All scripts`},{id:`@devices`,label:S.t(`mention @devices`),descriptionKey:`Smart home devices`}]}function Re({provider:e,isDark:t}){return U[e]?T(`img`,{src:`./img/${e}.svg`,alt:e,style:{...q,...t?{filter:`invert(0.85)`}:{}},onError:e=>{e.target.style.display=`none`}}):null}function ze(){try{let e=window.localStorage.getItem(`Editor.aiChatHistory`);return e?JSON.parse(e):[]}catch{return[]}}var Be=({onSend:n,disabled:c,themeType:l,hasSelection:p,selectionText:g,allScripts:_,model:y,availableModels:C,modelProviderMap:w,modelsLoading:E,onModelChange:k,mode:N,onModeChange:ee,currentLanguage:P})=>{let[F,I]=x(``),[L,R]=x(!1),[z,B]=x(``),[V,te]=x(0),H=h(null),U=h(-1),W=h(ze()),G=h(-1),ne=h(``),K=i(()=>{let e=Le().map(e=>({...e,description:S.t(e.descriptionKey)}));if(_)for(let t of _){let n=t.id.replace(/^script\.js\./,``).replace(/\./g,`/`);e.push({id:`@${n}`,label:`@${n}`,description:`${t.name} [${t.enabled?`active`:`inactive`}]`})}return e},[_]),q=i(()=>{if(!z)return K;let e=z.toLowerCase();return K.filter(t=>t.id.toLowerCase().includes(e)||t.description.toLowerCase().includes(e))},[K,z]);t(()=>{te(0)},[z]);let J=b(()=>{let e=F.trim();if(!e||c)return;let t=e,r=Ie(e);if(r){let e=p&&g?g:``,n=Fe({action:r.action,code:e,language:P||`javascript`,question:r.action===`ask`?r.rest:void 0,diagnostic:r.action===`fix`&&r.rest||void 0});n&&(t=n)}else p&&g&&(t=`[Selected code in editor]\n\`\`\`\n${g}\n\`\`\`\n\n${e}`);W.current.push(e),G.current=-1,ne.current=``;try{let e=W.current.slice(-50);window.localStorage.setItem(`Editor.aiChatHistory`,JSON.stringify(e))}catch{}n(t),I(``),R(!1),requestAnimationFrame(()=>{var e;return(e=H.current)==null?void 0:e.focus()})},[F,c,n,p,g,P]),Y=b(e=>{let t=U.current,n=H.current;if(t<0){let t=F?`${F}${e} `:`${e} `;I(t),R(!1),B(``),setTimeout(()=>{n&&(n.focus(),n.setSelectionRange(t.length,t.length))},0);return}let r=F.substring(0,t),i=(n==null?void 0:n.selectionStart)??F.length,a=`${r}${e} ${F.substring(i)}`;I(a),R(!1),B(``),U.current=-1,setTimeout(()=>{if(n){let t=r.length+e.length+1;n.focus(),n.setSelectionRange(t,t)}},0)},[F]),X=b(()=>{U.current=-1,B(``),R(e=>!e)},[]),re=b(e=>{let t=e.target.value;I(t);let n=e.target.selectionStart??t.length,r=t.substring(0,n).match(/@([\w/äöüÄÖÜß]*)$/);r?(U.current=n-r[0].length,B(r[1]),R(!0)):(R(!1),B(``))},[]),ae=b(e=>{if(L&&q.length>0){if(e.key===`ArrowDown`){e.preventDefault(),te(e=>(e+1)%q.length);return}if(e.key===`ArrowUp`){e.preventDefault(),te(e=>(e-1+q.length)%q.length);return}if(e.key===`Enter`||e.key===`Tab`){e.preventDefault(),Y(q[V].id);return}if(e.key===`Escape`){e.preventDefault(),R(!1);return}}if(e.key===`ArrowUp`&&!L&&W.current.length>0){let t=H.current,n=!t||t.selectionStart===0,r=!F.includes(`
|
|
26
|
-
`);if(n&&r){e.preventDefault(),G.current===-1?(ne.current=F,G.current=W.current.length-1):G.current>0&&G.current--,I(W.current[G.current]);return}}if(e.key===`ArrowDown`&&!L&&G.current>=0){let t=H.current,n=!t||t.selectionStart===F.length,r=!F.includes(`
|
|
27
|
-
`);if(n&&r){e.preventDefault(),G.current<W.current.length-1?(G.current++,I(W.current[G.current])):(G.current=-1,I(ne.current));return}}e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),J())},[J,L,q,V,Y,F]);return D(u,{sx:{borderTop:`1px solid`,borderColor:`divider`,position:`relative`},children:[L&&q.length>0&&T(a,{elevation:4,sx:{position:`absolute`,bottom:`100%`,left:8,right:8,maxHeight:200,overflow:`auto`,zIndex:10,mb:.5},children:T(r,{dense:!0,disablePadding:!0,children:q.slice(0,15).map((t,n)=>T(m,{selected:n===V,onClick:()=>Y(t.id),sx:{py:.25,minHeight:32},children:T(e,{primary:t.label,secondary:t.description,slotProps:{primary:{sx:{fontSize:`0.8rem`,fontWeight:500}},secondary:{sx:{fontSize:`0.7rem`}}}})},t.id))})}),N===`code`&&T(O,{label:`${S.t(`mention @devices`)} — ${S.t(`Smart home devices`)}`,size:`small`,variant:`outlined`,sx:{mx:1,mt:.5,maxWidth:`calc(100% - 16px)`}}),p&&g&&T(O,{icon:T(A,{sx:{fontSize:14}}),label:S.t(`Selected code as context`),size:`small`,variant:`outlined`,sx:{mx:1,mt:.5,maxWidth:`calc(100% - 16px)`}}),D(u,{sx:{mx:1,mt:.5,mb:.5,border:`1px solid`,borderColor:`divider`,borderRadius:1.5,overflow:`hidden`,"&:focus-within":{borderColor:`primary.main`}},children:[T(s,{inputRef:H,fullWidth:!0,multiline:!0,maxRows:6,placeholder:S.t(`Ask about your script...`),value:F,onChange:re,onKeyDown:ae,disabled:c,onBlur:()=>{setTimeout(()=>R(!1),200)},variant:`standard`,slotProps:{input:{disableUnderline:!0}},sx:{px:1.5,pt:1,pb:.5,"& .MuiInputBase-root":{fontSize:`0.875rem`}}}),D(u,{sx:{display:`flex`,alignItems:`center`,gap:.75,px:1,pb:.5},children:[T(v,{title:D(u,{sx:{fontSize:`0.8rem`,lineHeight:1.5,maxWidth:360},children:[T(u,{sx:{fontWeight:600,mb:.75},children:S.t(`AI chat mode`)}),D(u,{sx:{mb:.75},children:[D(`strong`,{children:[`💬 `,S.t(`Chat`)]}),` —`,` `,S.t(`Plain conversation. Use for questions, explanations, syntax help. Does not read or modify your scripts.`)]}),D(u,{sx:{mb:.75},children:[D(`strong`,{children:[`🤖 `,S.t(`Agent`)]}),` —`,` `,S.t(`For larger models with tool support. The AI can read, create, and edit scripts, look up datapoints, and browse the object tree — useful for "create a script that...", "which scripts use this state?" or "analyze my light script".`)]}),D(u,{children:[D(`strong`,{children:[`💻 `,S.t(`Code`)]}),` —`,` `,S.t(`For smaller models without tool support. Two-step script generator (plan then code) — useful for "create a script that..." or "write a Blockly rule for...". Output goes into the editor for smart-apply.`)]})]}),enterDelay:400,placement:`left`,children:D(d,{value:N,onChange:e=>ee(e.target.value),size:`small`,variant:`standard`,disableUnderline:!0,sx:{fontSize:`0.7rem`,color:`text.secondary`,border:`1px solid`,borderColor:`text.secondary`,borderRadius:3,bgcolor:`action.hover`,px:.75,"&:hover":{borderColor:`text.disabled`,bgcolor:`action.hover`},"& .MuiSelect-select":{py:`2px`,pr:`18px !important`,display:`flex`,alignItems:`center`,gap:.5}},children:[T(f,{value:`chat`,sx:{fontSize:`0.75rem`},title:S.t(`Plain conversation. Best for: general questions, syntax help, concept explanations.`),children:`💬 Chat`}),T(f,{value:`agent`,sx:{fontSize:`0.75rem`},title:S.t(`For larger models with tool support. Best for: creating, editing, or analyzing scripts; finding datapoint usages; inspecting the object tree.`),children:`🤖 Agent`}),T(f,{value:`code`,sx:{fontSize:`0.75rem`},title:S.t(`For smaller models without tool support. Best for: creating new JavaScript/TypeScript or Blockly scripts from a description.`),children:`💻 Code`})]})}),T(d,{value:y,onChange:e=>k(e.target.value),size:`small`,disabled:E||C.length===0,variant:`standard`,disableUnderline:!0,sx:{fontSize:`0.7rem`,color:`text.secondary`,border:`1px solid`,borderColor:`text.secondary`,borderRadius:3,bgcolor:`action.hover`,px:.75,"&:hover":{borderColor:`text.disabled`,bgcolor:`action.hover`},"& .MuiSelect-select":{py:`2px`,pr:`18px !important`,display:`flex`,alignItems:`center`,gap:.5}},children:C.map(e=>D(f,{value:e,sx:{fontSize:`0.75rem`,display:`flex`,gap:.5},children:[T(Re,{provider:w[e],isDark:l===`dark`}),e]},e))}),T(v,{title:S.t(`Mention scripts as context for the AI. Use @all for all scripts or @scriptName for a specific one.`),enterDelay:500,children:T(j,{size:`small`,onClick:X,sx:{p:`3px`,color:L?`primary.main`:`text.secondary`,border:`1px solid`,borderColor:L?`primary.main`:`text.secondary`,bgcolor:L?void 0:`action.hover`,borderRadius:3,"&:hover":{borderColor:`text.disabled`,bgcolor:`action.hover`}},children:T(ie,{sx:{fontSize:16}})})}),T(u,{sx:{flex:1}}),D(o,{variant:`caption`,sx:{color:`text.disabled`,fontSize:`0.65rem`,mr:.5,whiteSpace:`nowrap`},children:[`Enter `,S.t(`to send`)]}),T(v,{title:`${S.t(`Send`)} (Enter)`,children:T(`span`,{children:T(j,{color:`primary`,onClick:J,disabled:c||!F.trim(),size:`small`,sx:{p:.25},children:T(M,{sx:{fontSize:18}})})})})]})]})]})};p();var Ve=({socket:e,runningInstances:n,themeType:r,currentCode:a,currentLanguage:s,selectedCode:c,allScripts:l,editorApi:d,aiActionRequest:f,onAiActionConsumed:p,onRegisterInlineAsk:m,onInsertCode:g,onShowDiff:y,onApplyCode:x,currentScriptId:E,onClose:O})=>{var A;let M=h(null),{messages:N,isLoading:ee,error:P,model:F,availableModels:I,modelProviderMap:L,modelsLoading:R,modelsError:z,lastContextInfo:B,mode:V,setMode:te,setModel:H,sendMessage:U,triggerAiAction:W,askInline:G,clearChat:ne,retryLoadModels:K}=we(i(()=>({socket:e,runningInstances:n,currentCode:a,currentLanguage:s,allScripts:l,editorApi:d,currentScriptId:E}),[e,n,a,s,l,d,E]));t(()=>(m==null||m(G),()=>m==null?void 0:m(null)),[G,m]);let q=h(null);t(()=>{f&&q.current!==f&&(q.current=f,W(f),p==null||p())},[f,W,p]),t(()=>{var e;(e=M.current)==null||e.scrollIntoView({behavior:`smooth`})},[N]);let J=b(e=>{g==null||g(e)},[g]),Y=b((e,t)=>{y==null||y(e,t)},[y]),X=b(e=>{x==null||x(e)},[x]);return D(u,{sx:{display:`flex`,flexDirection:`column`,height:`100%`,bgcolor:`background.default`,"& .ai-chat-inline-code":{backgroundColor:`action.selected`,color:`text.primary`,border:`1px solid`,borderColor:`divider`}},children:[D(u,{sx:{display:`flex`,alignItems:`center`,gap:1,px:1,py:.5,borderBottom:`1px solid`,borderColor:`divider`,bgcolor:r===`dark`?`grey.900`:`grey.100`,flexShrink:0},children:[T(o,{variant:`subtitle2`,sx:{fontWeight:600,flex:1,color:`text.primary`},children:S.t(`AI Chat`)}),R&&T(w,{size:16}),T(v,{title:S.t(`New chat`),children:T(j,{size:`small`,onClick:ne,children:T(re,{sx:{fontSize:18}})})}),T(v,{title:S.t(`Close`),children:T(j,{size:`small`,onClick:O,children:T(_,{sx:{fontSize:18}})})})]}),(P||z)&&T(k,{severity:`error`,sx:{m:1,py:0},action:z?T(j,{size:`small`,onClick:K,children:T(C,{sx:{fontSize:16}})}):void 0,children:P||z}),B&&T(o,{variant:`caption`,sx:{px:1.5,py:.25,color:`text.secondary`,fontSize:`0.7rem`,bgcolor:`action.hover`,borderBottom:`1px solid`,borderColor:`divider`,flexShrink:0},children:B}),D(u,{sx:{flex:1,overflow:`auto`,py:1},children:[N.length===0&&!ee&&D(u,{sx:{display:`flex`,flexDirection:`column`,alignItems:`center`,justifyContent:`center`,height:`100%`,color:`text.secondary`,px:3,textAlign:`center`},children:[T(o,{variant:`body2`,sx:{mb:1},children:S.t(`Ask questions about your script, request changes, or generate new code.`)}),D(o,{variant:`caption`,color:`text.disabled`,children:[`Enter `,S.t(`to send`),`, Shift+Enter `,S.t(`for new line`)]})]}),N.filter(e=>e.role!==`system`).map(e=>T(Me,{message:e,themeType:r,currentLanguage:s,onInsertCode:J,onShowDiff:Y,onApplyCode:X},e.id)),ee&&((A=N[N.length-1])==null?void 0:A.content)===``&&D(u,{sx:{display:`flex`,alignItems:`center`,gap:1,px:2,py:1},children:[T(w,{size:16}),T(o,{variant:`caption`,color:`text.secondary`,children:S.t(`Thinking...`)})]}),T(`div`,{ref:M})]}),T(Be,{onSend:U,disabled:ee||I.length===0,themeType:r,hasSelection:!!c,selectionText:c,allScripts:l,model:F,availableModels:I,modelProviderMap:L,modelsLoading:R,onModelChange:H,mode:V,onModeChange:te,currentLanguage:s})]})};export{Ve as default,Ie as n,Fe as t};
|