iobroker.javascript 10.2.4 → 10.3.0

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.
Files changed (186) hide show
  1. package/README.md +10 -21
  2. package/admin/assets/AiChatPanel-CpY4Bun-.js +27 -0
  3. package/admin/assets/{AiChatService-Bsp_rhVx.js → AiChatService-QKcpW4jQ.js} +1 -1
  4. package/admin/assets/AiDiffView-DscPfZ38.js +1 -0
  5. package/admin/assets/{AiInlineProvider-BxOW88xU.js → AiInlineProvider-DTSPKoXG.js} +1 -1
  6. package/admin/assets/BlocklyEditor-BZyoN1JE.js +301 -0
  7. package/admin/assets/Compile-B0uHjrBE.css +1 -0
  8. package/admin/assets/Compile-Oss28m_f.js +165 -0
  9. package/admin/assets/Debugger-teJTIU-2.js +15 -0
  10. package/admin/assets/Documentation-uz4Ut9pT.js +4339 -0
  11. package/admin/assets/ExpandMore-V5Ix1QB1.js +1 -0
  12. package/admin/assets/FbEditor-B8S-mCvc.css +1 -0
  13. package/admin/assets/FbEditor-aOZ-RpPV.js +15 -0
  14. package/admin/assets/Import-BIC5Ee9z.js +1 -0
  15. package/admin/assets/NotificationsActive-BdzH44gp.js +1 -0
  16. package/admin/assets/RulesEditor-CcDVthPa.js +1 -0
  17. package/admin/assets/{ScriptEditor-BCGahS47.js → ScriptEditor-CviB6Hif.js} +2 -2
  18. package/admin/assets/ScriptEditorVanillaMonaco-ByuXwybM.js +3 -0
  19. package/admin/assets/Send-Mdo32jMb.js +1 -0
  20. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-BnL93BgK.js +1 -0
  21. 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 +1217 -0
  22. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DVaMIZyC.js +9 -0
  23. package/admin/assets/aiPromptBuilder-yTB6N2VT.js +1 -0
  24. package/admin/assets/blocklyTheme-CGhU3cEO.js +1 -0
  25. package/admin/assets/blocks_action-BQ4O7NRE.js +1 -0
  26. package/admin/assets/{blocks_convert-CLb0DLyc.js → blocks_convert-0VBjfhqQ.js} +1 -1
  27. package/admin/assets/blocks_logic-DAo99xDr.js +1 -0
  28. package/admin/assets/blocks_number-C--e19NU.js +1 -0
  29. package/admin/assets/blocks_object-D0TPhdzg.js +1 -0
  30. package/admin/assets/blocks_procedures-DgTxgXdB.js +3 -0
  31. package/admin/assets/{blocks_sendto-BxCMg9X4.js → blocks_sendto-CRIrtOUc.js} +1 -1
  32. package/admin/assets/blocks_switch-b_GYfF0n.js +2 -0
  33. package/admin/assets/blocks_system-BdkUdSsc.js +1 -0
  34. package/admin/assets/blocks_text-DSFhEVOf.js +1 -0
  35. package/admin/assets/blocks_time-CqALAiJp.js +1 -0
  36. package/admin/assets/blocks_timeout-yrOD2pZp.js +1 -0
  37. package/admin/assets/{blocks_trigger-XivsIDE5.js → blocks_trigger-DeAYXpSS.js} +1 -1
  38. package/admin/assets/{cronHoverProvider-BZMOFHO_.js → cronHoverProvider-DoO2_tpG.js} +1 -1
  39. package/admin/assets/{field_cron-CxKi__cX.js → field_cron-D3Ts_s9M.js} +1 -1
  40. package/admin/assets/{field_oid-CJIYiGxY.js → field_oid-BRNXredg.js} +1 -1
  41. package/admin/assets/{field_script-CehplM7L.js → field_script-3X6ousg7.js} +1 -1
  42. package/admin/assets/helpers-BTGaTdnT.js +1 -0
  43. package/admin/assets/{hostInit-Bs-bStPF.js → hostInit-2h2Cbsaw.js} +1 -1
  44. package/admin/assets/iconLibraryData-B5fiyl1C.js +1 -0
  45. package/admin/assets/index-BHhhebRG.css +1 -0
  46. package/admin/assets/index-CbQlIKB_.js +156 -0
  47. package/admin/assets/{inlineChatWidget-NIvdRGmU.js → inlineChatWidget-BwQVCPkx.js} +1 -1
  48. package/admin/assets/{inlineDiffController-Qh402KhK.js → inlineDiffController-BsDDsDHn.js} +1 -1
  49. package/admin/assets/loadBlocks-RpqM7PwO.js +117 -0
  50. package/admin/assets/loadMonaco-BVOEahNw.js +1 -0
  51. package/admin/assets/{mf-entry-bootstrap-0-019228a5.js → mf-entry-bootstrap-0-0deef484.js} +3 -3
  52. package/admin/assets/{pendingShares-B3t6ewri.js → pendingShares-BaAadIDv.js} +1 -1
  53. package/admin/assets/reactour.esm-DX9ZgYlx.js +137 -0
  54. package/admin/assets/stateHoverProvider-BEadnSXp.js +11 -0
  55. package/admin/assets/tileFbd-CWAy7R7m.svg +85 -0
  56. package/admin/custom/assets/Components-FkGDIlId.js +1 -0
  57. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-Cs88NUCd.js +1 -0
  58. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-P-8ffWXw.js +1 -0
  59. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-ZVuRAEo5.js +1 -0
  60. 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 +1217 -0
  61. 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 +1 -0
  62. 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 +1 -0
  63. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__date_mf_2_fns__loadShare__.js-CnhNjamd.js +1 -0
  64. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare__leaflet__loadShare__.js-im3edKNs.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__leaflet__loadShare__.js-Dz7BFJqH.js} +1 -1
  65. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-B0olko2J.js +1 -0
  66. 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 +122 -0
  67. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__leaflet__prebuild__-xPcBaiTQ.js +1 -0
  68. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-Byvr2uOb.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-CXpyx8Vy.js} +1 -1
  69. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__react_mf_2_dom_mf_1_client__prebuild__-DuFBE5fh.js +9 -0
  70. package/admin/custom/assets/{hostInit-IJMNq3h7.js → hostInit-6oh4UY2k.js} +1 -1
  71. package/admin/custom/assets/iconLibraryData-B5fiyl1C.js +1 -0
  72. package/admin/custom/assets/index-BrlyEy6J.js +1 -0
  73. package/admin/custom/assets/lib-BmDlTzq2.js +3 -0
  74. package/admin/custom/assets/{mf-entry-bootstrap-0-f149bc46.js → mf-entry-bootstrap-0-ad1cd7d0.js} +3 -3
  75. package/admin/custom/assets/pendingShares-kV2kwejX.js +1 -0
  76. package/admin/custom/assets/rolldown-runtime-Dqfqb5bO.js +1 -0
  77. package/admin/custom/customComponents.js +3 -2
  78. package/admin/custom/i18n/en.json +39 -39
  79. package/admin/custom/i18n/es.json +1 -1
  80. package/admin/custom/i18n/fr.json +2 -2
  81. package/admin/custom/i18n/it.json +1 -1
  82. package/admin/custom/i18n/nl.json +2 -2
  83. package/admin/custom/i18n/pt.json +2 -2
  84. package/admin/custom/i18n/ru.json +2 -2
  85. package/admin/custom/i18n/uk.json +1 -1
  86. package/admin/custom/i18n/zh-cn.json +1 -1
  87. package/admin/i18n/de.json +1 -1
  88. package/admin/i18n/en.json +115 -115
  89. package/admin/i18n/fr.json +115 -115
  90. package/admin/i18n/it.json +115 -115
  91. package/admin/i18n/nl.json +115 -115
  92. package/admin/i18n/pl.json +1 -1
  93. package/admin/i18n/pt.json +115 -115
  94. package/admin/i18n/ru.json +115 -115
  95. package/admin/i18n/uk.json +115 -115
  96. package/admin/i18n/zh-cn.json +115 -115
  97. package/admin/mf-manifest.json +1 -1
  98. package/admin/mf-stats.json +1 -1
  99. package/admin/remoteEntry.js +2 -2
  100. package/admin/tab.html +3 -7
  101. package/build/lib/fb/analyze.js +288 -0
  102. package/build/lib/fb/analyze.js.map +1 -0
  103. package/build/lib/fb/blocks.js +605 -0
  104. package/build/lib/fb/blocks.js.map +1 -0
  105. package/build/lib/fb/generate.js +326 -0
  106. package/build/lib/fb/generate.js.map +1 -0
  107. package/build/lib/fb/graph.js +240 -0
  108. package/build/lib/fb/graph.js.map +1 -0
  109. package/build/lib/fb/index.js +57 -0
  110. package/build/lib/fb/index.js.map +1 -0
  111. package/build/lib/fb/js.js +33 -0
  112. package/build/lib/fb/js.js.map +1 -0
  113. package/build/lib/fb/layout.js +205 -0
  114. package/build/lib/fb/layout.js.map +1 -0
  115. package/build/lib/fb/library.js +657 -0
  116. package/build/lib/fb/library.js.map +1 -0
  117. package/build/lib/fb/runtime.js +793 -0
  118. package/build/lib/fb/runtime.js.map +1 -0
  119. package/build/lib/fb/time.js +76 -0
  120. package/build/lib/fb/time.js.map +1 -0
  121. package/build/lib/fb/types.js +19 -0
  122. package/build/lib/fb/types.js.map +1 -0
  123. package/build/lib/fb/user.js +78 -0
  124. package/build/lib/fb/user.js.map +1 -0
  125. package/build/lib/javascript.d.ts +17 -17
  126. package/build/lib/mirror.js +4 -0
  127. package/build/lib/mirror.js.map +1 -1
  128. package/build/lib/sandbox.js +44 -0
  129. package/build/lib/sandbox.js.map +1 -1
  130. package/build/main.js +66 -1
  131. package/build/main.js.map +1 -1
  132. package/build/types.d.ts +9 -1
  133. package/docs/de/README.md +1 -1
  134. package/docs/de/fbd.md +274 -0
  135. package/docs/de/javascript.md +2167 -0
  136. package/docs/en/fbd.md +260 -0
  137. package/docs/en/javascript.md +28 -30
  138. package/io-package.json +52 -28
  139. package/package.json +8 -8
  140. package/admin/assets/AiChatPanel-AZko1BsN.js +0 -27
  141. package/admin/assets/AiDiffView-Cri2QFh1.js +0 -1
  142. package/admin/assets/Debugger-CVDh3kgz.js +0 -15
  143. package/admin/assets/Error-Ch2nx5uC.js +0 -1
  144. package/admin/assets/Import-XKVP-nRT.js +0 -1
  145. package/admin/assets/RulesEditor-DsO4cKIk.js +0 -1
  146. package/admin/assets/ScriptEditorVanillaMonaco-BDAw2Bw6.js +0 -3
  147. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-BMAFQFoH.js +0 -1
  148. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__113183188387379__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-D-gi6Mty.js +0 -1217
  149. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__113183188387379__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-CDctpiPx.js +0 -9
  150. package/admin/assets/aiPromptBuilder-aJfHa-eU.js +0 -1
  151. package/admin/assets/blocks_action-DS28sNfo.js +0 -1
  152. package/admin/assets/blocks_logic-Dpp2fwlu.js +0 -1
  153. package/admin/assets/blocks_number-N4IfHvYD.js +0 -1
  154. package/admin/assets/blocks_object-uK7FHVhS.js +0 -1
  155. package/admin/assets/blocks_procedures-C_KD0Bm6.js +0 -3
  156. package/admin/assets/blocks_switch-C8Rls5pK.js +0 -2
  157. package/admin/assets/blocks_system-CEQnj5fY.js +0 -1
  158. package/admin/assets/blocks_text-BDEWxu0P.js +0 -1
  159. package/admin/assets/blocks_time-aHQQK1Uz.js +0 -1
  160. package/admin/assets/blocks_timeout-C2L93TLJ.js +0 -1
  161. package/admin/assets/helpers-DiwtLpXM.js +0 -1
  162. package/admin/assets/index-B0FfAYMN.js +0 -871
  163. package/admin/assets/index-CXaeqPRy.css +0 -1
  164. package/admin/assets/stateHoverProvider-BkW15VMN.js +0 -9
  165. package/admin/assets/virtualExposes-DgGB-18P.js +0 -1
  166. package/admin/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__iobroker_javascript__remoteEntry_js-CiidVc0O.js +0 -1
  167. package/admin/assets/virtual_mf-exposes___mfe_internal__iobroker_javascript__remoteEntry_js-ChiJXsfH.js +0 -1
  168. package/admin/custom/assets/Components-SGnA-3W_.js +0 -1
  169. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-Bx3X6TLB.js +0 -1
  170. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-Cc7MmJgr.js +0 -1
  171. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-CdvEvX5z.js +0 -1
  172. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-D5NaoeJi.js +0 -1217
  173. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-Cbgw_a3f.js +0 -1
  174. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.js-CMr75K5w.js +0 -1
  175. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare__date_mf_2_fns__loadShare__.js-DKIvPDPX.js +0 -1
  176. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-D50aYKgD.js +0 -1
  177. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-CEzQFX7o.js +0 -122
  178. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__prebuild__leaflet__prebuild__-BUDmnAcx.js +0 -1
  179. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__136440932828998__prebuild__react_mf_2_dom_mf_1_client__prebuild__-D_1oh1WH.js +0 -9
  180. package/admin/custom/assets/index-7r4VklMp.js +0 -1
  181. package/admin/custom/assets/lib-DDU2Oe48.js +0 -3
  182. package/admin/custom/assets/pendingShares-DarGQhyO.js +0 -1
  183. package/admin/custom/assets/rolldown-runtime-BcKkbAw3.js +0 -1
  184. package/admin/custom/assets/virtualExposes-C0IqMANQ.js +0 -1
  185. package/admin/custom/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-CqKvh5Xu.js +0 -1
  186. package/admin/custom/assets/virtual_mf-exposes___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-DrBN_S5o.js +0 -2
package/io-package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "javascript",
4
- "version": "10.2.4",
4
+ "version": "10.3.0",
5
5
  "blockedVersions": [
6
6
  "8.0.0",
7
7
  "8.0.1"
@@ -40,6 +40,32 @@
40
40
  "Matthias Kleine <info@haus-automatisierung.com>"
41
41
  ],
42
42
  "news": {
43
+ "10.3.0": {
44
+ "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
+ "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)",
46
+ "ru": "Редактор кода (Monaco), блоки Blockly и Rules загружаются только при открытии такого скрипта, поэтому редактор запускается быстрее\nДобавлены функциональные блок-схемы (FBD, в стиле CFC): таймеры, счетчики, триггеры, сравнение, арифметика, конверсии, управление, календарь (cron, sun events), журнал и сообщения, а также блок с собственным JavaScript, привязанный к состояниям IOBroker. См. [описание] (docs/en/fbd.md)",
47
+ "pt": "O editor de código (Monaco), o Blockly e o Rules só são carregados quando um script é aberto, então o editor começa mais rápido\nForam adicionados diagramas de blocos funcionais (FBD, no estilo CFC): temporizadores, contadores, flip-flops, bordas, comparação, aritmética, conversões, controle, calendário, log e mensagens e um bloco com JavaScript próprio, conectado aos estados do IOBroker. Veja a descrição (docs/en/fbd.md)",
48
+ "nl": "De blokken code-editor (Monaco), Blockly en de Rules worden alleen geladen als een dergelijk script wordt geopend, zodat de editor sneller start\nFunctieblokdiagrammen toegevoegd (FBD, in de stijl van CFC): timers, tellers, flip-flops, randen, vergelijking, rekenen, conversies, controle, kalender (cron, zonnegebeurtenissen), logboek en berichten, en een blok met eigen JavaScript - overgezet naar IOBroker-staten. Zie [de beschrijving] (docs/en/fbd.md)",
49
+ "fr": "L'éditeur de code (Monaco), Blockly et les blocs Rules ne sont chargés que lorsqu'un script de ce type est ouvert.\nAjout de diagrammes de blocs fonctionnels (FBD, style CFC) : chronomètres, compteurs, bascules, bords, comparaison, arithmétique, conversions, contrôle, calendrier (cron, sun events), journal et messages, et un bloc avec son propre JavaScript, connecté aux états d'IObroker. Voir [la description] (docs/en/fbd.md)",
50
+ "it": "I blocchi Code Editor (Monaco), Blockly e Rules si caricano solo all'apertura di quel tipo di script\nAggiunti diagrammi a blocchi funzionali (FBD, in stile CFC): timer, contatori, flip-flop, edge, confronto, aritmetica, conversioni, controllo, calendario (cron, sun events), log e messaggi e un blocco con JavaScript proprio, collegato agli stati IOBroker. Vedi [descrizione] (docs/en/fbd.md)",
51
+ "es": "El editor de código (Mónaco), los bloques Blockly y Rules solo se cargan cuando se abre un guion de ese tipo, por lo que el editor se inicia más rápido\nDiagramas de bloques de funciones (FBD, al estilo de CFC): temporizadores, contadores, chanclas, bordes, comparación, aritmética, conversiones, control, calendario (cron, sun events), registro y mensajes, y un bloque con su propio JavaScript, conectado a los estados de IOBroker. Vea [la descripción] (docs/en/fbd.md)",
52
+ "pl": "Edytor kodu (Monaco), Blockly i bloki Reguły są ładowane tylko po otwarciu tego rodzaju skryptu, więc edytor uruchamia się szybciej\nDodano diagramy blokowe funkcji (FBD, w stylu CFC): timery, liczniki, klapki, krawędzie, porównanie, arytmetyka, konwersje, sterowanie, kalendarz (cron, zdarzenia słoneczne), dzienniki i wiadomości oraz blok z własnym JavaScript - podłączony do stanów ioBroker. Patrz [opis] (docs/en/fbd.md)",
53
+ "uk": "Редактор коду (Монако), блоки Blockly та Rules завантажуються лише тоді, коли відкривається такий сценарій, тому редактор запускається швидше\nДодані функціональні блокові діаграми (FBD, в стилі CFC): таймери, лічильники, шльопанці, ребра, порівняння, арифметика, перетворення, управління, календар (cron, sun events), журнал і повідомлення, а також блок з власним JavaScript - підключений до станів IObroker. Див. [опис] (docs/uk/fbd.md)",
54
+ "zh-cn": "代码编辑器(摩纳哥)、Blockly 和 Rules 块仅在打开此类脚本时加载,因此编辑器启动速度更快\n添加了函数方框图(FBD,采用 CFC 风格):计时器、计数器、触发器、边缘、比较、算术、转换、控制、日历(cron、sun 事件)、日志和消息,以及带有自己的 JavaScript 的方块(连接到 IOBroker 状态)。参见 [描述](docs/en/fbd.md)"
55
+ },
56
+ "10.2.5": {
57
+ "en": "Added the functions help dialog in editor",
58
+ "de": "Hilfedialog im Editor hinzugefügt",
59
+ "ru": "Добавлен диалог справки по функциям в редакторе",
60
+ "pt": "Adicionou a ajuda de funções no editor",
61
+ "nl": "De helpdialoog voor functies toegevoegd in de editor",
62
+ "fr": "Ajout de la boîte d'aide aux fonctions de l'éditeur",
63
+ "it": "Aggiunte le funzioni di aiuto in editor",
64
+ "es": "Añadió las funciones de ayuda en el editor",
65
+ "pl": "Dodano okno dialogowe pomocy funkcji w edytorze",
66
+ "uk": "Додано діалогове вікно допомоги функцій в редакторі",
67
+ "zh-cn": "在编辑器中添加了功能帮助对话框"
68
+ },
43
69
  "10.2.4": {
44
70
  "en": "Rules: selection of state fixed\nFixed debugger",
45
71
  "de": "Regeln: Bundeslandwahl fest\nFester Debugger",
@@ -104,32 +130,6 @@
104
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",
105
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Коли два постачальники пропонують однойменну модель - наприклад, проксі та постачальник, який стоїть за нею, - хто з них обслуговував, це вирішувалось тим, хто відповідав першим, і він може змінюватися від одного перезавантаження до іншого. Постачальник, налаштований першим, виграє зараз, тому прямий маршрут є кращим перед проксі-сервером",
106
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当两个提供商提供同名模型时(例如代理及其背后的供应商),则由最先回答的人决定,并且可以从一次重新加载更改为下一次重新加载。首先配置的提供商现在获胜,因此直接路由优先于代理"
107
- },
108
- "10.1.4": {
109
- "en": "Rules: the text of an action can round the trigger value with `%.1s` - any number of digits after the decimal point, also `%.2old` for the old value - formatted with the decimal separator of the system, so `Kühlschrank zu warm (%.1s°C)` gives `29,4°C` where `%s` gave `29.400000000000002°C`\nCorrected the function block in blockly\nA custom OpenAI-compatible AI endpoint answered \"Invalid API key\" in the inline completion and while loading the model list, although the test button in the settings said \"ok\": both asked the adapter for the provider `openai`, and the adapter picks the key by that name, so they used the \"OpenAI API key\" instead of the \"Custom API key\". The custom endpoint is now addressed as what it is, everywhere (#2369)\nA configured \"Custom API Base URL\" also redirected every request meant for OpenAI itself to that address - with the OpenAI key attached and no way to switch it off. The base URL now belongs to the custom endpoint alone, so both can be used side by side. If the key of your custom endpoint is in the \"OpenAI API key\" field, move it to the \"Custom API key\" field; the adapter writes a warning in the log if it finds such a setup (#2369)",
110
- "de": "Regeln: Der Text einer Aktion kann den Triggerwert mit `%.1s` runden — beliebig viele Nachkommastellen, auch `%.2old` für den alten Wert — formatiert mit dem Dezimaltrennzeichen des Systems, also `Kühlschrank zu warm (%.1s°C) `ergibt `29,4°C`, während `%s` `29.400000000000002°C` ergibt\nFunktionsblock in Blockly korrigiert\nEin benutzerdefinierter OpenAI-kompatibler KI-Endpunkt antwortete beim Laden der Modellliste mit „Ungültiger API-Schlüssel“, obwohl der Testbutton in den Einstellungen „ok“ sagte: Beide fragten den Adapter nach dem Anbieter `openai`, und der Adapter wählt den Schlüssel mit diesem Namen aus, also nutzten sie den „OpenAI API Key“ statt des „Custom API Key“. Der benutzerdefinierte Endpunkt wird jetzt überall behandelt (#2369)\nEine konfigurierte „Custom API Base URL“ leitete auch jede Anfrage für OpenAI an diese Adresse um — mit OpenAI-Key und ohne Abschaltmöglichkeit. Die Basis-URL gehört nun nur zum Endpunkt, also beide nebeneinander. Wenn der Schlüssel Ihres Endpunkts im Feld „OpenAI API Key“ steht, schreibt der Adapter eine Warnung in das Log (#2369)",
111
- "ru": "Правила: в тексте действия можно округлить значение триггера до «%.1s» — любое количество цифр после десятичной точки, а также «%.2old» для старого значения — отформатированное с использованием десятичного разделителя системы, поэтому `Kühlschrank zu warm (%.1s°C) `дает значение `29,4°C`, где `%s` даёт `29,400000000000002°C`\nИсправлен функциональный блок в blockly\nСпециальная конечная точка искусственного интеллекта, совместимая с OpenAI, ответила «Неверный ключ API» при встраиваемом заполнении и загрузке списка моделей, хотя на кнопке тестирования в настройках было написано «ОК»: обе команды запросили у адаптера поставщика `openai`, и адаптер выбирает ключ под этим именем, поэтому вместо «Custom API key» они использовали «ключ OpenAI API». Настраиваемая конечная точка теперь везде рассматривается как есть (#2369)\nНастроенный «Custom API Base URL» также перенаправлял каждый запрос, предназначенный для самого OpenAI, на этот адрес — при этом ключ OpenAI был прикреплен, и его нельзя было отключить. Теперь базовый URL-адрес принадлежит только настраиваемой конечной точке, поэтому их можно использовать одновременно. Если ключ вашей пользовательской конечной точки находится в поле «Ключ OpenAI API», переместите его в поле «Custom API key»; если адаптер обнаружит такую настройку, в журнал запишет предупреждение (#2369)",
112
- "pt": "Regras: o texto de uma ação pode arredondar o valor do gatilho com `%.1s` - qualquer número de dígitos após o ponto decimal, também `%.2old` para o valor antigo - formatado com o separador decimal do sistema. 2°C”\nCorrigiu o bloco de função em bloco\nUm endpoint de IA compatível com OpenAI respondeu “chave de API inválida” no preenchimento em linha e ao carregar a lista de modelos, embora o botão de teste nas configurações dissesse “ok”: ambos pediram ao adaptador o provedor `openai` e o adaptador escolheu a chave com esse nome, então eles usaram a “chave de API OpenAI” em vez da “chave de API personalizada”. O endpoint personalizado agora é o que é, em todo lugar (#2369)\nUm “URL base de API personalizado” também redirecionava cada solicitação do OpenAI para esse endereço — com a chave OpenAI anexada e sem como desligá-la. O URL base agora pertence ao endpoint personalizado e pode ser usado lado a lado. Se a chave do seu endpoint estiver no campo “Chave de API OpenAI”, mova-a para “Chave de API personalizada”; o adaptador grava um aviso no log (#2369)",
113
- "nl": "Regels: de tekst van een actie kan de triggerwaarde afronden met `%.1s` - een willekeurig aantal cijfers achter de komma, ook `%.2oud` voor de oude waarde - opgemaakt met het decimale scheidingsteken van het systeem, zodat `Kühlschrank zu warm (%.1s°C) `geeft `29,4°C` waarbij `%s` `29.4000002°C` gaf\nHet functieblok in blockly gecorrigeerd\nEen aangepast AI-eindpunt dat compatibel is met OpenAI antwoordde „Ongeldige API-sleutel” in de inline-aanvulling en tijdens het laden van de modellenlijst, hoewel op de testknop in de instellingen „OK” stond: beiden vroegen de adapter naar de provider `openai`, en de adapter kiest de sleutel met die naam, dus gebruikten ze de „OpenAI API-sleutel” in plaats van de „Aangepaste API-sleutel”. Het aangepaste eindpunt wordt nu overal weergegeven zoals het is (#2369)\nEen geconfigureerde „Custom API Base URL” heeft ook elk verzoek dat voor OpenAI zelf was bedoeld, omgeleid naar dat adres - met de OpenAI-sleutel eraan gekoppeld en zonder mogelijkheid om het uit te schakelen. De basis-URL behoort nu alleen tot het aangepaste eindpunt, dus beide kunnen naast elkaar worden gebruikt. Als de sleutel van uw aangepaste eindpunt zich in het veld „OpenAI API-sleutel” bevindt, verplaats deze dan naar het veld „Aangepaste API-sleutel”; de adapter schrijft een waarschuwing in het logboek als er een dergelijke instelling wordt gevonden (#2369)",
114
- "fr": "Règles : le texte d'une action peut arrondir la valeur de déclenchement par « %.1s », un nombre quelconque de chiffres après la virgule, et « %.2old » pour l'ancienne valeur, formaté avec le séparateur décimal du système, donc « Kühlschrank zu warm (%.1s°C) » donne « 29,4°C » où « %s` a donné 29,400000000000002°C »\nCorrection du bloc de fonctions dans Blockly\nUn terminal IA personnalisé compatible avec OpenAI a répondu « Clé API non valide » en ligne et en chargeant la liste des modèles, mais le bouton de test des paramètres indiquait « OK » : les deux ont demandé à l'adaptateur le fournisseur « openai », et l'adaptateur a choisi la clé portant ce nom. Ils ont donc utilisé la « clé API OpenAI » au lieu de la « clé API personnalisée ». Le point de terminaison personnalisé est désormais traité tel quel, partout (#2369)\nUne « URL de base API personnalisée » configurée redirigeait toutes les requêtes destinées à OpenAI vers cette adresse, avec la clé OpenAI attachée, sans moyen de la désactiver. L'URL de base n'appartient qu'au point de terminaison personnalisé, donc côte à côte. Si la clé de votre terminal personnalisé se trouve dans le champ « Clé API OpenAI », l'adaptateur écrit un avertissement dans le journal s'il détecte une telle configuration (#2369)",
115
- "it": "Regole: il testo di un'azione può arrotondare il valore del trigger con «%.1s» - qualsiasi numero di cifre dopo la virgola, anche «%.2old» per il vecchio valore - con il separatore decimale del sistema, quindi «Kühlschrank zu warm (%.1s°C)» dà «29,4°C» dove «%s» dà «29.40000000000000000\" 02 °C»\nCorretto il blocco funzione in blocco\nUn endpoint AI personalizzato compatibile con OpenAI ha risposto «Chiave API non valida» nel completamento in linea e durante il caricamento dell'elenco dei modelli, anche se il pulsante di test diceva «ok»: entrambi hanno chiesto al provider «openai» e l'adattatore ha scelto la chiave con quel nome. L'endpoint personalizzato ora è così, ovunque (#2369)\nUn «Custom API Base URL» reindirizzava anche tutte le richieste di OpenAI a quell'indirizzo, con la chiave OpenAI allegata e senza modo di spegnerla. L'URL di base ora appartiene solo all'endpoint personalizzato. Se la chiave del suo endpoint è nel campo «OpenAI API key», la sposti nel campo «Custom API key»; l'adattatore scrive un avviso nel log se trova tale setup (#2369)",
116
- "es": "Reglas: el texto de una acción puede redondear el valor de activación con `%.1s` (cualquier número de dígitos después de la coma decimal, también `%.2old» para el valor anterior, formateado con el separador decimal del sistema, por lo que `Kühlschrank zu warm (%.1s°C) `da 29,4°C`, donde `%s` daba 29,40000000002°C\nSe corrigió el bloque de funciones en blockly\nUn punto final de IA personalizado compatible con OpenAI respondió «Clave de API no válida» al terminar en línea y al cargar la lista de modelos, aunque el botón de prueba de la configuración decía «vale»: ambos pidieron al adaptador el proveedor `openai` y el adaptador escogió la clave con ese nombre, por lo que usaron la «clave de API de OpenAI» en lugar de la «clave de API personalizada». El punto final personalizado ahora se dirige como es, en todas partes (#2369)\nUna «URL base de API personalizada» configurada también redirigía todas las solicitudes de OpenAI a esa dirección, con la clave de OpenAI adjunta y sin forma de desactivarla. La URL base ahora pertenece solo al punto final personalizado, por lo que pueden usarse. Si la clave de su punto final personalizado está en el campo «Clave API OpenAI», muévala al campo «Clave API personalizada»; el adaptador escribe un aviso en el registro si encuentra esa configuración (#2369)",
117
- "pl": "Reguły: tekst akcji może zaokrąglić wartość wyzwalającą o `%.1s` - dowolną liczbę cyfr po przecinku, także `%.2old` dla starej wartości - sformatowaną za pomocą separatora dziesiętnego systemu, więc `Kühlschrank zu warm (%.1s°C) `daje `29,4°C` gdzie `%s` dało `29.400000000000002°C`\nPoprawiono blok funkcji w bloku\nNiestandardowy punkt końcowy AI zgodny z OpenAI odpowiedział na „Nieprawidłowy klucz API” podczas uzupełniania linii i podczas ładowania listy modeli, chociaż przycisk testowy w ustawieniach powiedział „ok”: obaj poprosili adapter o dostawcę `openai`, a adapter wybiera klucz pod tą nazwą, więc użyli „klucza API OpenAI” zamiast „Custom API key”. Niestandardowy punkt końcowy jest teraz adresowany tak, jak jest, wszędzie (#2369)\nSkonfigurowany „Custom API Base URL” przekierował również każde żądanie przeznaczone dla samego OpenAI na ten adres - z dołączonym kluczem OpenAI i bez możliwości jego wyłączenia. Podstawowy adres URL należy teraz do samego niestandardowego punktu końcowego, więc oba mogą być używane obok siebie. Jeśli klucz niestandardowego punktu końcowego znajduje się w polu „Klucz API OpenAI”, przenieś go do pola „Custom API key”; adapter zapisuje ostrzeżenie w dzienniku, jeśli znajdzie taką konfigurację (#2369)",
118
- "uk": "Правила: текст дії може округлити значення тригера з `%.1s `- будь-якою кількістю цифр після десяткової коми, також `%.2old` для старого значення - відформатоване десятковим роздільником системи, тому `Kühlschrank zu warm (%.1s°C)` дає `29,4°C`, де `%s` дав `29.400000000000002°C`\nВиправлено функціональний блок в blockly\nСпеціальна кінцева точка AI, сумісна з OpenAI, відповіла «Недійсний ключ API» у вбудованому доповненні та під час завантаження списку моделей, хоча на кнопці тестування в налаштуваннях було написано «ok»: обидва запитали у адаптера постачальника `openai`, а адаптер вибирає ключ під цим ім'ям, тому вони використовували «ключ API OpenAI» замість «Custom API key». Користувацьку кінцеву точку тепер адресовано як те, що вона є, скрізь (#2369)\nНалаштована «Custom API Base URL» також перенаправляла кожен запит, призначений для самої OpenAI, на цю адресу - з прикріпленим ключем OpenAI і без можливості його вимкнути. Базова URL-адреса тепер належить лише користувацькій кінцевій точці, тому обидві можуть бути використані поруч. Якщо ключ вашої користувацької кінцевої точки знаходиться в полі «OpenAI API key», перемістіть його в поле «Custom API key»; адаптер записує попередження в журнал, якщо знайде таку настройку (#2369)",
119
- "zh-cn": "规则:动作文本可以用 `%.1s` 对触发值进行四舍五入——小数点后的任意位数,旧值也是 `%.2old` ——使用系统的十进制分隔符进行格式化,因此 `Kühlschrank zu warm (%.1s°C) `给出 `29,4°C`,其中 `%s` 给出 `29.4000000000002°C`\n方块更正了功能块\n一个兼容 OpenAI 的自定义 AI 端点在行内完成和加载模型列表时回答 “无效 API 密钥”,尽管设置中的测试按钮显示 “确定”:两者都要求适配器提供提供商 “openai”,而适配器按该名称选择密钥,因此他们使用 “OpenAI API 密钥” 而不是 “自定义 API 密钥”。现在,自定义终端节点随处可见 (#2369)\n配置的 “自定义API基础网址” 还将所有发送给OpenAI本身的请求重定向到该地址——附加了OpenAI密钥,无法将其关闭。基本 URL 现在仅属于自定义端点,因此两者可以并排使用。如果您的自定义终端节点的密钥位于 “OpenAI API 密钥” 字段中,请将其移至 “自定义 API 密钥” 字段;如果适配器发现此类设置,则会在日志中写入警告 (#2369)"
120
- },
121
- "10.1.3": {
122
- "en": "The plain text export named its files after the script ID instead of the script name, so every dot of a name came out as an underscore - `HK-Balkontuer_v0.1` was exported as `HK-Balkontuer_v0_1.js`, and importing it back renamed the script to that. The files are now named after the script (#2364)\nImporting a plain text export treated a dot inside a file name as a folder level, so `PW-TV-Control_v0.6.js` created a folder `PW-TV-Control_v0` containing a script named `6`. Only the directories of the ZIP are folders now (#2364)\nThe folder icons in the script tree were drawn at less than half the size of the script icons next to them: they spaced themselves with a padding, and since `CssBaseline` sets `box-sizing: border-box` that padding was subtracted from their 20px instead of being added to them. They use a margin now, like the script icons always did (#2360)\nThe log below the editor could not be resized while a script was open: the editor area guessed its height from the height the tabs and the toolbar were expected to have, hung over the bottom edge of its pane and covered the 8px splitter with the horizontal scrollbar of the editor, which swallowed the mouse click. The three parts now share the height as a flex column (#2351)\nThe script list cut off long names, although there was still free space next to them: the space for the buttons at the end of a row was a fixed 185px, which is more than the three buttons occupy, and it did not account for the icon column\nFixed the Blockly comment block: the text was written in white on the yellow block and could not be read, the editor opened somewhere else on the page instead of over the block, and on a smartphone or tablet it did not open at all and left the whole workspace unusable until the page was reloaded (#2348)\nFixed the script mirror for folder names containing regular expression characters: a folder called e.g. `Lampen (Flur` aborted the synchronization with a `SyntaxError`, a folder called e.g. `[ab]` silently synchronized the scripts of another folder (#2239)\nThe Blockly block \"http (POST)\" got a \"content type\" selector, so an API that insists on `Content-Type: application/json` no longer needs an `exec` block. \"automatic\" is the default and behaves exactly as before, \"own\" allows any other type (#1983)\n`getSchedules()` returned the schedules of the time wizard of **all** scripts, even without the argument `true`. Now only the schedules of the own script are returned (#2164)\n`clearSchedule()` did not accept the objects that `getSchedules()` returns for schedules of the time wizard, so such a schedule stayed in the script and in the schedule counter (#2164)\n`clearSchedule()` can now clear the CRON jobs of other scripts too, as documented for `getSchedules(true)` (#2164)\n`getSchedules()` no longer lists the already canceled schedules of the own script in an `onStop` callback (#2164)",
123
- "de": "Beim Export im Klartext wurden die Dateien nach der Skript-ID anstatt nach dem Skriptnamen benannt. Dadurch wurde jeder Punkt im Namen als Unterstrich dargestellt – beispielsweise wurde `HK-Balkontuer_v0.1` als `HK-Balkontuer_v0_1.js` exportiert, und beim erneuten Import wurde das Skript entsprechend umbenannt. Die Dateien sind nun nach dem Skript benannt (#2364).\nBeim Importieren eines Klartextexports wurde ein Punkt im Dateinamen als Ordnerebene interpretiert, sodass `PW-TV-Control_v0.6.js` einen Ordner `PW-TV-Control_v0` mit einem Skript namens `6` erstellte. Nur die Verzeichnisse der ZIP-Datei sind jetzt Ordner (#2364).\nDie Ordnersymbole im Skriptbaum wurden mit weniger als der halben Größe der daneben liegenden Skriptsymbole dargestellt: Sie hatten einen Innenabstand (Padding), und da `CssBaseline` `box-sizing: border-box` festlegt, wurde dieser Innenabstand von ihren 20 Pixeln abgezogen, anstatt addiert zu werden. Sie verwenden nun einen Außenabstand (Margin), wie es bei den Skriptsymbolen immer der Fall war (#2360).\nDer Bereich unterhalb des Editors konnte nicht in der Größe angepasst werden, solange ein Skript geöffnet war: Der Editorbereich berechnete seine Höhe anhand der erwarteten Höhe der Tabs und der Symbolleiste, ragte über den unteren Rand des Fensters hinaus und verdeckte den 8-Pixel-Trennstreifen mit der horizontalen Scrollleiste des Editors, wodurch der Mausklick blockiert wurde. Die drei Bereiche teilen sich nun die Höhe als Flexbox-Spalte (#2351).\nDie Skriptliste schnitt lange Namen ab, obwohl daneben noch Platz war: Der Platz für die Schaltflächen am Ende einer Zeile betrug feste 185 Pixel, was mehr ist, als die drei Schaltflächen einnehmen, und die Spalte für die Symbole nicht berücksichtigte.\nDer Blockly-Kommentarblock wurde korrigiert: Der Text wurde in Weiß auf dem gelben Block geschrieben und war unlesbar, der Editor öffnete sich an einer anderen Stelle auf der Seite anstatt über dem Block, und auf einem Smartphone oder Tablet öffnete er sich überhaupt nicht und der gesamte Arbeitsbereich war unbrauchbar, bis die Seite neu geladen wurde (#2348).\nDas Problem mit der Skriptspiegelung für Ordnernamen, die reguläre Ausdrücke enthalten, wurde behoben: Ein Ordner namens z. B. `Lampen (Flur` brach die Synchronisierung mit einem `SyntaxError` ab, ein Ordner namens z. B. `[ab]` synchronisierte stillschweigend die Skripte eines anderen Ordners (#2239).\nDer Blockly-Block „http (POST)“ hat einen „Content-Type“-Selektor erhalten, sodass eine API, die auf `Content-Type: application/json` besteht, keinen `exec`-Block mehr benötigt. „automatic“ ist die Standardeinstellung und verhält sich wie zuvor, „own“ erlaubt jeden anderen Typ (#1983).\n`getSchedules()` gab die Zeitpläne des Zeitassistenten **aller** Skripte zurück, selbst ohne das Argument `true`. Jetzt werden nur noch die Zeitpläne des eigenen Skripts zurückgegeben (#2164).\n`clearSchedule()` akzeptierte die Objekte nicht, die `getSchedules()` für Zeitpläne des Zeitassistenten zurückgibt, sodass ein solcher Zeitplan im Skript und im Zeitplanzähler verblieb (#2164).\n`clearSchedule()` kann nun auch die CRON-Jobs anderer Skripte löschen, wie für `getSchedules(true)` dokumentiert (#2164).\n`getSchedules()` listet die bereits abgebrochenen Zeitpläne des eigenen Skripts nicht mehr in einem `onStop`-Callback auf (#2164).",
124
- "ru": "При экспорте в текстовом формате файлы назывались по идентификатору скрипта, а не по его имени, поэтому каждая точка в имени отображалась как нижнее подчеркивание — `HK-Balkontuer_v0.1` экспортировался как `HK-Balkontuer_v0_1.js`, а при обратном импорте скрипт переименовывался в это имя. Теперь файлы называются по имени скрипта (#2364)\nПри импорте файла в виде простого текста точка внутри имени файла рассматривалась как уровень папки, поэтому файл `PW-TV-Control_v0.6.js` создал папку `PW-TV-Control_v0`, содержащую скрипт с именем `6`. Теперь только каталоги ZIP-архива являются папками (#2364)\nЗначки папок в дереве скриптов отображались в размере менее половины размера значков скриптов рядом с ними: они отступали, и поскольку `CssBaseline` устанавливает `box-sizing: border-box`, этот отступ вычитался из их 20 пикселей, а не добавлялся к ним. Теперь они используют поля, как и всегда использовали значки скриптов (#2360)\nРазмер области под редактором нельзя было изменить, пока открыт скрипт: область редактора определяла свою высоту исходя из ожидаемой высоты вкладок и панели инструментов, выступала за нижний край своей панели и закрывала 8-пиксельный разделитель горизонтальной полосой прокрутки редактора, которая «проглатывала» щелчок мыши. Теперь все три части имеют одинаковую высоту в виде гибкой колонки (#2351)\nВ списке скриптов длинные имена были обрезаны, хотя рядом с ними оставалось свободное место: пространство для кнопок в конце строки составляло фиксированные 185 пикселей, что больше, чем занимают три кнопки, и это не учитывало столбец с иконками.\nИсправлена ошибка в блоке комментариев Blockly: текст писался белым цветом на желтом фоне и не читался, редактор открывался в другом месте страницы, а не поверх блока, и на смартфоне или планшете он вообще не открывался, оставляя все рабочее пространство недоступным до перезагрузки страницы (#2348)\nИсправлена ошибка зеркалирования скриптов для папок с именами, содержащими символы регулярных выражений: папка с именем, например, `Lampen (Flur`), прерывала синхронизацию с ошибкой `SyntaxError`, а папка с именем, например, `[ab]` молча синхронизировала скрипты другой папки (#2239)\nБлок Blockly \"http (POST)\" получил селектор \"тип содержимого\", поэтому API, который настаивает на `Content-Type: application/json`, больше не нуждается в блоке `exec`. \"automatic\" является значением по умолчанию и ведет себя точно так же, как и раньше, \"own\" допускает любой другой тип (#1983)\nФункция `getSchedules()` возвращала расписания мастера времени **всех** скриптов, даже без аргумента `true`. Теперь возвращаются только расписания собственного скрипта (#2164)\nФункция `clearSchedule()` не принимала объекты, возвращаемые функцией `getSchedules()` для расписаний мастера времени, поэтому такое расписание оставалось в скрипте и в счетчике расписаний (#2164)\nТеперь функция `clearSchedule()` может очищать задания CRON и других скриптов, как это описано в документации для функции `getSchedules(true)` (#2164).\nФункция `getSchedules()` больше не отображает уже отмененные расписания собственного скрипта в функции обратного вызова `onStop` (#2164)",
125
- "pt": "A exportação em texto simples nomeava os arquivos de acordo com o ID do script em vez do nome do script, então cada ponto de um nome era interpretado como um sublinhado - `HK-Balkontuer_v0.1` foi exportado como `HK-Balkontuer_v0_1.js`, e ao importá-lo de volta, o script foi renomeado para esse nome. Os arquivos agora estão nomeados de acordo com o script (#2364)\nA importação de uma exportação de texto simples tratava um ponto dentro de um nome de arquivo como um nível de pasta, então `PW-TV-Control_v0.6.js` criou uma pasta `PW-TV-Control_v0` contendo um script chamado `6`. Somente os diretórios do ZIP são pastas agora (#2364)\nOs ícones de pasta na árvore de scripts eram desenhados com menos da metade do tamanho dos ícones de script ao lado: eles se espaçavam com um preenchimento, e como `CssBaseline` define `box-sizing: border-box`, esse preenchimento era subtraído de seus 20px em vez de ser adicionado. Agora eles usam uma margem, como os ícones de script sempre usaram (#2360)\nO log abaixo do editor não podia ser redimensionado enquanto um script estivesse aberto: a área do editor estimava sua altura com base na altura esperada das abas e da barra de ferramentas, ultrapassava a borda inferior do painel e cobria o divisor de 8px com a barra de rolagem horizontal do editor, que anulava o clique do mouse. As três partes agora compartilham a mesma altura como uma coluna flexível (#2351)\nA lista de scripts cortou nomes longos, embora ainda houvesse espaço livre ao lado deles: o espaço para os botões no final de uma linha era fixo em 185px, o que é mais do que os três botões ocupam, e não levava em conta a coluna de ícones.\nCorrigido o bloco de comentários do Blockly: o texto era escrito em branco no bloco amarelo e não podia ser lido, o editor abria em outro lugar da página em vez de sobre o bloco e em um smartphone ou tablet ele não abria de jeito nenhum e deixava todo o espaço de trabalho inutilizável até que a página fosse recarregada (#2348)\nCorrigido o espelhamento de scripts para nomes de pastas contendo caracteres de expressão regular: uma pasta chamada, por exemplo, `Lampen (Flur)` abortava a sincronização com um `SyntaxError`, uma pasta chamada, por exemplo, `[ab]` sincronizava silenciosamente os scripts de outra pasta (#2239)\nO bloco Blockly \"http (POST)\" recebeu um seletor de \"tipo de conteúdo\", então uma API que exige `Content-Type: application/json` não precisa mais de um bloco `exec`. \"automatic\" é o padrão e se comporta exatamente como antes, \"own\" permite qualquer outro tipo (#1983)\n`getSchedules()` retornava os agendamentos do assistente de tempo de **todos** os scripts, mesmo sem o argumento `true`. Agora, apenas os agendamentos do próprio script são retornados (#2164)\n`clearSchedule()` não aceitou os objetos que `getSchedules()` retorna para agendamentos do assistente de tempo, então tal agendamento permaneceu no script e no contador de agendamentos (#2164)\n`clearSchedule()` agora também pode limpar os trabalhos CRON de outros scripts, conforme documentado para `getSchedules(true)` (#2164)\n`getSchedules()` não lista mais os agendamentos já cancelados do próprio script em um retorno de chamada `onStop` (#2164)",
126
- "nl": "Bij de export in platte tekst werden de bestanden vernoemd naar de script-ID in plaats van de scriptnaam, waardoor elke punt in een naam als een underscore werd weergegeven - `HK-Balkontuer_v0.1` werd geëxporteerd als `HK-Balkontuer_v0_1.js`, en bij het terug importeren werd het script hernoemd naar die naam. De bestanden zijn nu vernoemd naar het script (#2364).\nBij het importeren van een platte tekstexport werd een punt in een bestandsnaam als mapniveau behandeld, dus `PW-TV-Control_v0.6.js` creëerde een map `PW-TV-Control_v0` met daarin een script met de naam `6`. Alleen de mappen in het ZIP-bestand zijn nu nog mappen (#2364)\nDe mappictogrammen in de scriptstructuur werden getekend op minder dan de helft van de grootte van de scriptpictogrammen ernaast: ze hadden een opvulling (padding) en omdat `CssBaseline` `box-sizing: border-box` instelt, werd die opvulling van hun 20px afgetrokken in plaats van erbij opgeteld. Ze gebruiken nu een marge, zoals de scriptpictogrammen altijd al deden (#2360).\nHet logbestand onder de editor kon niet worden aangepast qua grootte terwijl een script open was: het editorgebied schatte zijn hoogte op basis van de hoogte die de tabbladen en de werkbalk zouden moeten hebben, stak over de onderrand van het paneel heen en bedekte de 8px-splitter met de horizontale schuifbalk van de editor, die de muisklik blokkeerde. De drie onderdelen delen nu de hoogte als een flexibele kolom (#2351).\nDe scriptlijst kortte lange namen af, hoewel er nog vrije ruimte naast was: de ruimte voor de knoppen aan het einde van een rij was een vaste 185px, wat meer is dan de drie knoppen innemen, en er werd geen rekening gehouden met de pictogramkolom.\nHet probleem met het Blockly-commentaarblok is opgelost: de tekst werd in het wit op het gele blok geschreven en was onleesbaar, de editor opende ergens anders op de pagina in plaats van over het blok heen, en op een smartphone of tablet opende hij helemaal niet, waardoor de hele werkruimte onbruikbaar werd totdat de pagina opnieuw werd geladen (#2348)\nHet probleem met de scriptspiegeling voor mapnamen die reguliere expressietekens bevatten, is opgelost: een map met de naam bijvoorbeeld `Lampen (Flur)` brak de synchronisatie af met een `SyntaxError`, terwijl een map met de naam bijvoorbeeld `[ab]` de scripts van een andere map stilzwijgend synchroniseerde (#2239).\nHet Blockly-blok \"http (POST)\" heeft een \"content type\"-selector gekregen, waardoor een API die aandringt op `Content-Type: application/json` geen `exec`-blok meer nodig heeft. \"automatic\" is de standaardinstelling en gedraagt zich precies zoals voorheen, \"own\" staat elk ander type toe (#1983).\n`getSchedules()` gaf de schema's van de tijdwizard van **alle** scripts terug, zelfs zonder het argument `true`. Nu worden alleen de schema's van het eigen script teruggestuurd (#2164)\n`clearSchedule()` accepteerde de objecten die `getSchedules()` retourneert voor de schema's van de tijdwizard niet, dus bleef een dergelijk schema in het script en in de schemateller staan (#2164).\n`clearSchedule()` kan nu ook de CRON-taken van andere scripts wissen, zoals gedocumenteerd voor `getSchedules(true)` (#2164).\n`getSchedules()` geeft niet langer de reeds geannuleerde schema's van het eigen script weer in een `onStop`-callback (#2164)",
127
- "fr": "L'exportation en texte brut nommait les fichiers d'après l'identifiant du script au lieu de son nom. Par conséquent, chaque point d'un nom était remplacé par un tiret bas : `HK-Balkontuer_v0.1` était exporté en `HK-Balkontuer_v0_1.js`, et l'importation du script l'a renommé en conséquence. Les fichiers portent désormais le nom du script (#2364).\nL'importation d'un fichier texte brut interprétait un point dans un nom de fichier comme un niveau de dossier ; ainsi, `PW-TV-Control_v0.6.js` créait un dossier `PW-TV-Control_v0` contenant un script nommé `6`. Seuls les répertoires de l'archive ZIP sont désormais considérés comme des dossiers (#2364).\nLes icônes de dossiers dans l'arborescence des scripts étaient dessinées à une taille inférieure à la moitié de celle des icônes de scripts adjacentes : elles étaient espacées par un remplissage, et comme `CssBaseline` définit `box-sizing: border-box`, ce remplissage était soustrait de leurs 20 px au lieu d'y être ajouté. Elles utilisent désormais une marge, comme le faisaient auparavant les icônes de scripts (#2360).\nImpossible de redimensionner le journal situé sous l'éditeur lorsqu'un script était ouvert : la zone de l'éditeur, dont la hauteur était estimée à partir de celle des onglets et de la barre d'outils, dépassait le bord inférieur de son panneau et masquait le séparateur de 8 px avec la barre de défilement horizontale, qui empêchait le clic de la souris d'être pris en compte. Les trois éléments partagent désormais la même hauteur sous forme de colonne flexible (#2351).\nLa liste des scripts tronquait les noms longs, bien qu'il restât de l'espace libre à côté : l'espace réservé aux boutons en fin de ligne était de 185 px, ce qui est supérieur à la surface occupée par les trois boutons, et ne tenait pas compte de la colonne d'icônes.\nCorrection du bloc de commentaires Blockly : le texte était écrit en blanc sur le bloc jaune et était illisible, l’éditeur s’ouvrait ailleurs sur la page au lieu de se superposer au bloc, et sur un smartphone ou une tablette, il ne s’ouvrait pas du tout et rendait l’espace de travail inutilisable jusqu’au rechargement de la page (#2348)\nCorrection du problème de synchronisation des scripts pour les noms de dossiers contenant des caractères d'expression régulière : un dossier appelé par exemple `Lampen (Flur)` interrompait la synchronisation avec une `SyntaxError`, un dossier appelé par exemple `[ab]` synchronisait silencieusement les scripts d'un autre dossier (#2239)\nLe bloc Blockly « http (POST) » dispose désormais d'un sélecteur de type de contenu. Ainsi, une API exigeant `Content-Type: application/json` n'a plus besoin d'un bloc `exec`. La valeur par défaut est « automatic » et son comportement reste inchangé ; « own » autorise tout autre type (#1983).\nLa fonction `getSchedules()` renvoyait les planifications de l'assistant de planification de l'heure de **tous** les scripts, même sans l'argument `true`. Désormais, seules les planifications du script lui-même sont renvoyées (#2164).\n`clearSchedule()` n'acceptait pas les objets que `getSchedules()` renvoie pour les planifications de l'assistant de planification, donc une telle planification est restée dans le script et dans le compteur de planification (#2164)\n`clearSchedule()` peut désormais également effacer les tâches CRON d'autres scripts, comme indiqué dans la documentation de `getSchedules(true)` (#2164).\n`getSchedules()` ne liste plus les planifications déjà annulées du propre script dans un rappel `onStop` (#2164)",
128
- "it": "L'esportazione in testo semplice denominava i file in base all'ID dello script anziché al nome dello script stesso, quindi ogni punto del nome veniva visualizzato come un trattino basso: `HK-Balkontuer_v0.1` veniva esportato come `HK-Balkontuer_v0_1.js` e, importandolo nuovamente, lo script veniva rinominato in quel modo. Ora i file sono denominati in base allo script (#2364).\nL'importazione di un'esportazione in testo semplice trattava il punto all'interno del nome del file come livello di cartella, quindi `PW-TV-Control_v0.6.js` creava una cartella `PW-TV-Control_v0` contenente uno script chiamato `6`. Ora solo le directory dello ZIP sono cartelle (#2364)\nLe icone delle cartelle nell'albero degli script venivano disegnate con dimensioni inferiori alla metà rispetto alle icone degli script adiacenti: si distanziavano con un padding e, poiché `CssBaseline` imposta `box-sizing: border-box`, tale padding veniva sottratto dai loro 20px anziché essere aggiunto. Ora utilizzano un margine, come hanno sempre fatto le icone degli script (#2360).\nIl registro sotto l'editor non poteva essere ridimensionato mentre uno script era aperto: l'area dell'editor deduceva la sua altezza dall'altezza prevista per le schede e la barra degli strumenti, sporgeva dal bordo inferiore del suo riquadro e copriva il divisore da 8px con la barra di scorrimento orizzontale dell'editor, che inghiottiva il clic del mouse. Ora le tre parti condividono l'altezza come una colonna flex (#2351)\nL'elenco degli script troncava i nomi lunghi, sebbene ci fosse ancora spazio libero accanto a essi: lo spazio per i pulsanti alla fine di una riga era fisso a 185px, che è più di quanto occupato dai tre pulsanti, e non teneva conto della colonna delle icone.\nRisolto il problema del blocco commenti di Blockly: il testo veniva scritto in bianco sul blocco giallo e non era leggibile, l'editor si apriva in un altro punto della pagina invece che sopra il blocco e su smartphone o tablet non si apriva affatto, lasciando l'intera area di lavoro inutilizzabile fino al ricaricamento della pagina (#2348)\nCorretto il mirroring degli script per i nomi delle cartelle contenenti caratteri di espressione regolare: una cartella chiamata ad esempio `Lampen (Flur` interrompeva la sincronizzazione con un `SyntaxError`, una cartella chiamata ad esempio `[ab]` sincronizzava silenziosamente gli script di un'altra cartella (#2239)\nIl blocco Blockly \"http (POST)\" ha ora un selettore \"content type\", quindi un'API che richiede `Content-Type: application/json` non necessita più di un blocco `exec`. \"automatic\" è l'impostazione predefinita e si comporta esattamente come prima, \"own\" consente qualsiasi altro tipo (#1983).\n`getSchedules()` restituiva gli orari della procedura guidata oraria di **tutti** gli script, anche senza l'argomento `true`. Ora vengono restituiti solo gli orari del proprio script (#2164)\n`clearSchedule()` non accetta gli oggetti che `getSchedules()` restituisce per le pianificazioni della procedura guidata oraria, quindi tale pianificazione rimane nello script e nel contatore delle pianificazioni (#2164)\n`clearSchedule()` ora può cancellare anche i processi CRON di altri script, come documentato per `getSchedules(true)` (#2164)\n`getSchedules()` non elenca più le pianificazioni già annullate del proprio script in una callback `onStop` (#2164)",
129
- "es": "La exportación en texto plano nombró los archivos según el ID del script en lugar del nombre del script, por lo que cada punto del nombre se convirtió en un guion bajo: `HK-Balkontuer_v0.1` se exportó como `HK-Balkontuer_v0_1.js`, y al importarlo de nuevo, el script se renombró así. Ahora los archivos se nombran según el script (#2364).\nAl importar una exportación de texto plano, el punto dentro del nombre del archivo se interpretaba como un nivel de carpeta, por lo que `PW-TV-Control_v0.6.js` creaba una carpeta llamada `PW-TV-Control_v0` que contenía un script llamado `6`. Ahora solo los directorios del archivo ZIP son carpetas (#2364).\nLos iconos de carpeta en el árbol de scripts se dibujaban con un tamaño inferior a la mitad del de los iconos de script adyacentes: se espaciaban con un relleno, y dado que `CssBaseline` establece `box-sizing: border-box`, ese relleno se restaba de sus 20 px en lugar de sumarse. Ahora usan un margen, como siempre lo hicieron los iconos de script (#2360).\nEl registro debajo del editor no se podía redimensionar mientras había un script abierto: el área del editor calculaba su altura a partir de la altura esperada de las pestañas y la barra de herramientas, sobresalía del borde inferior de su panel y cubría el divisor de 8 px con la barra de desplazamiento horizontal del editor, que absorbía el clic del ratón. Ahora las tres partes comparten la altura como una columna flexible (#2351).\nLa lista de scripts truncaba los nombres largos, aunque aún quedaba espacio libre junto a ellos: el espacio para los botones al final de una fila era fijo, de 185 px, más de lo que ocupan los tres botones, y no tenía en cuenta la columna de iconos.\nSe corrigió el bloque de comentarios de Blockly: el texto se escribía en blanco sobre el bloque amarillo y no se podía leer, el editor se abría en otra parte de la página en lugar de sobre el bloque, y en un teléfono inteligente o tableta no se abría en absoluto y dejaba todo el espacio de trabajo inutilizable hasta que se recargaba la página (#2348).\nSe corrigió el espejo de scripts para nombres de carpetas que contienen caracteres de expresiones regulares: una carpeta llamada, por ejemplo, `Lampen (Flur` abortaba la sincronización con un `SyntaxError`, una carpeta llamada, por ejemplo, `[ab]` sincronizaba silenciosamente los scripts de otra carpeta (#2239)\nEl bloque de Blockly \"http (POST)\" ahora tiene un selector de \"tipo de contenido\", por lo que una API que insiste en `Content-Type: application/json` ya no necesita un bloque `exec`. \"automatic\" es el valor predeterminado y se comporta exactamente igual que antes, \"own\" permite cualquier otro tipo (#1983).\n`getSchedules()` devolvía los horarios del asistente de tiempo de **todos** los scripts, incluso sin el argumento `true`. Ahora solo se devuelven los horarios del propio script (#2164).\n`clearSchedule()` no aceptaba los objetos que `getSchedules()` devuelve para los horarios del asistente de tiempo, por lo que dicho horario permaneció en el script y en el contador de horarios (#2164).\n`clearSchedule()` ahora también puede borrar las tareas CRON de otros scripts, como se documenta para `getSchedules(true)` (#2164).\n`getSchedules()` ya no muestra las programaciones canceladas del propio script en una llamada de retorno `onStop` (#2164)",
130
- "pl": "Eksport zwykłego tekstu nazwał pliki identyfikatorem skryptu, a nie jego nazwą, więc każda kropka w nazwie była podkreślona – „HK-Balkontuer_v0.1” został wyeksportowany jako „HK-Balkontuer_v0_1.js”, a po ponownym zaimportowaniu zmienił nazwę skryptu na tę. Pliki noszą teraz nazwy pochodzące od skryptu (#2364).\nImportowanie eksportu zwykłego tekstu traktowało kropkę w nazwie pliku jako poziom folderu, więc `PW-TV-Control_v0.6.js` utworzyło folder `PW-TV-Control_v0` zawierający skrypt o nazwie `6`. Teraz tylko katalogi w pliku ZIP są folderami (#2364).\nIkony folderów w drzewie skryptów były narysowane w rozmiarze mniejszym niż połowa rozmiaru ikon skryptów obok nich: były oddzielone odstępem, a ponieważ `CssBaseline` ustawia `box-sizing: border-box`, odstęp ten został odjęty od ich 20 pikseli zamiast zostać do nich dodany. Teraz używają marginesu, tak jak zawsze ikony skryptów (#2360).\nRozmiar logu pod edytorem nie mógł zostać zmieniony, gdy skrypt był otwarty: obszar edytora odgadł swoją wysokość na podstawie wysokości, jaką miały mieć zakładki i pasek narzędzi, zawisł nad dolną krawędzią panelu i zakrył 8-pikselowy separator poziomym paskiem przewijania edytora, co uniemożliwiało kliknięcie myszką. Te trzy części mają teraz wspólną wysokość jako elastyczna kolumna (#2351).\nLista skryptów obcięła długie nazwy, chociaż obok nich wciąż było wolne miejsce: przestrzeń na przyciski na końcu wiersza wynosiła stałe 185 px, co jest więcej niż zajmują trzy przyciski, i nie uwzględniało kolumny z ikonami\nNaprawiono blok komentarza Blockly: tekst był napisany na biało na żółtym bloku i nie dało się go odczytać, edytor otwierał się w innym miejscu strony zamiast nad blokiem, a na smartfonie lub tablecie w ogóle się nie otwierał i cała przestrzeń robocza pozostawała bezużyteczna do momentu ponownego załadowania strony (#2348)\nNaprawiono lustrzane odbicie skryptów dla nazw folderów zawierających znaki wyrażeń regularnych: folder o nazwie np. `Lampen (Flur` przerywał synchronizację z błędem `SyntaxError`, folder o nazwie np. `[ab]` po cichu synchronizował skrypty innego folderu (#2239)\nBlok Blockly „http (POST)” otrzymał selektor „typu zawartości”, więc API, które wymaga „Content-Type: application/json”, nie potrzebuje już bloku „exec”. Domyślnym typem jest „automatic”, który zachowuje się dokładnie tak samo jak wcześniej, „own” dopuszcza każdy inny typ (#1983).\nFunkcja `getSchedules()` zwróciła harmonogramy kreatora czasu **wszystkich** skryptów, nawet bez argumentu `true`. Teraz zwracane są tylko harmonogramy własnego skryptu (#2164).\n`clearSchedule()` nie akceptował obiektów zwracanych przez `getSchedules()` dla harmonogramów kreatora czasu, więc taki harmonogram pozostał w skrypcie i liczniku harmonogramu (#2164)\n`clearSchedule()` może teraz czyścić zadania CRON także innych skryptów, zgodnie z dokumentacją dla `getSchedules(true)` (#2164)\n`getSchedules()` nie wyświetla już anulowanych harmonogramów własnego skryptu w wywołaniu zwrotnym `onStop` (#2164)",
131
- "uk": "Експорт у звичайний текст назвав свої файли за ідентифікатором скрипта, а не за назвою скрипта, тому кожна крапка в назві відображалася як символ підкреслення – `HK-Balkontuer_v0.1` було експортовано як `HK-Balkontuer_v0_1.js`, а його зворотний імпорт перейменував скрипт на це. Файли тепер названі за назвою скрипта (#2364)\nІмпорт експорту звичайного тексту обробляв крапку всередині назви файлу як рівень папки, тому `PW-TV-Control_v0.6.js` створив папку `PW-TV-Control_v0`, що містить скрипт під назвою `6`. Тепер лише каталоги ZIP-архіву є папками (#2364)\nРозмір іконок папок у дереві скриптів був меншим, ніж половина розміру іконок скриптів поруч: вони мали інтервал між собою з відступом, і оскільки `CssBaseline` встановлює `box-sizing: border-box`, цей відступ віднімався від їхніх 20px, а не додавався до них. Тепер вони використовують відступ, як і завжди використовували іконки скриптів (#2360)\nРозмір журналу під редактором не можна було змінити, коли скрипт був відкритий: область редактора визначала свою висоту на основі висоти вкладок та панелі інструментів, нависала над нижнім краєм своєї панелі та перекривала роздільник розміром 8 пікселів горизонтальною смугою прокручування редактора, яка поглинала клацання миші. Тепер три частини мають однакову висоту як гнучкий стовпець (#2351).\nСписок скриптів обрізав довгі назви, хоча поруч із ними все ще залишався вільний простір: простір для кнопок у кінці рядка становив фіксовані 185 пікселів, що більше, ніж займають три кнопки, і це не враховувало стовпець значків.\nВиправлено блок коментарів Blockly: текст писався білим кольором на жовтому блоці та не міг бути прочитаний, редактор відкривався деінде на сторінці, а не над блоком, а на смартфоні чи планшеті він взагалі не відкривався та залишав увесь робочий простір непридатним для використання до перезавантаження сторінки (#2348)\nВиправлено дзеркало скриптів для імен папок, що містять символи регулярних виразів: папка з назвою, наприклад, `Lampen (Flur`, переривала синхронізацію з помилкою `SyntaxError`, папка з назвою, наприклад, `[ab]`, непомітно синхронізувала скрипти іншої папки (#2239)\nБлок Blockly \"http (POST)\" отримав селектор \"content type\", тому API, який наполягає на `Content-Type: application/json`, більше не потребує блоку `exec`. \"automatic\" є значенням за замовчуванням і поводиться точно так само, як і раніше, \"own\" дозволяє будь-який інший тип (#1983)\n`getSchedules()` повертав розклади майстра часу **всіх** скриптів, навіть без аргументу `true`. Тепер повертаються лише розклади власного скрипта (#2164)\n`clearSchedule()` не приймав об'єкти, які повертає `getSchedules()` для розкладів майстра часу, тому такий розклад залишався у скрипті та в лічильнику розкладів (#2164)\n`clearSchedule()` тепер може очищати CRON-завдання інших скриптів, як задокументовано для `getSchedules(true)` (#2164)\n`getSchedules()` більше не відображає вже скасовані розклади власного скрипта у зворотному виклику `onStop` (#2164)",
132
- "zh-cn": "纯文本导出时,文件名使用的是脚本 ID 而不是脚本名称,因此脚本名称中的每个点号都被转换成了下划线——例如,`HK-Balkontuer_v0.1` 被导出为 `HK-Balkontuer_v0_1.js`,重新导入后,脚本名称也随之更改。现在,文件名已正确更改为脚本名称 (#2364)。\n导入纯文本导出文件时,文件名中的点号会被识别为文件夹级别,因此 `PW-TV-Control_v0.6.js` 会创建一个名为 `PW-TV-Control_v0` 的文件夹,其中包含一个名为 `6` 的脚本。现在只有 ZIP 文件中的目录才是文件夹(#2364)。\n脚本树中的文件夹图标绘制尺寸不到旁边脚本图标的一半:它们通过内边距来保持间距,而由于 `CssBaseline` 设置了 `box-sizing: border-box`,所以这个内边距从它们的 20px 宽度中减去了,而不是加到了宽度上。现在它们使用外边距,就像脚本图标一直以来那样 (#2360)。\n当脚本打开时,编辑器下方的日志区域无法调整大小:编辑器区域会根据标签页和工具栏的预期高度来估算自身高度,导致其超出面板底部边缘,并且编辑器的水平滚动条会覆盖 8 像素的分隔线,从而吞噬鼠标点击。现在,这三个部分共享高度,形成一个弹性列(#2351)。\n脚本列表会截断过长的名称,尽管名称旁边还有剩余空间:每行末尾按钮的空间固定为 185 像素,这比三个按钮实际占用的空间要大,而且也没有考虑到图标列。\n修复了 Blockly 评论块的问题:文本显示在黄色块上时为白色,无法阅读;编辑器打开的位置在页面的其他位置而不是评论块上方;在智能手机或平板电脑上,编辑器根本无法打开,导致整个工作区无法使用,直到页面重新加载为止 (#2348)\n修复了文件夹名称包含正则表达式字符时的脚本镜像问题:例如,名为 `Lampen (Flur)` 的文件夹会因 `SyntaxError` 而中止同步,例如,名为 `[ab]` 的文件夹会静默同步另一个文件夹的脚本 (#2239)\nBlockly 的“http (POST)”代码块新增了“content type”选择器,因此,如果 API 要求使用 `Content-Type: application/json`,则不再需要 `exec` 代码块。“automatic”是默认值,其行为与之前完全相同;“own”则允许使用任何其他类型(#1983)。\n`getSchedules()` 函数会返回**所有**脚本的时间向导日程表,即使没有指定参数 `true` 也是如此。现在,它只会返回自身脚本的日程表 (#2164)。\n`clearSchedule()` 不接受时间向导的 `getSchedules()` 返回的日程对象,因此这样的日程会保留在脚本和日程计数器中 (#2164)\n`clearSchedule()` 现在也可以清除其他脚本的 CRON 作业,如 `getSchedules(true)` 的文档中所述 (#2164)\n`getSchedules()` 函数不再在 `onStop` 回调函数中列出自身脚本已取消的日程安排 (#2164)"
133
133
  }
134
134
  },
135
135
  "platform": "Javascript/Node.js",
@@ -611,7 +611,7 @@
611
611
  "language": "javascript",
612
612
  "views": {
613
613
  "javascript": {
614
- "map": "function(doc) { if (doc.type === 'script' && doc.common.engineType.match(/^[jJ]ava[sS]cript|^[cC]offee[sS]cript|^[tT]ype[sS]cript|^Blockly|^Rules/)) emit(doc.common.name, doc); }"
614
+ "map": "function(doc) { if (doc.type === 'script' && doc.common.engineType.match(/^[jJ]ava[sS]cript|^[cC]offee[sS]cript|^[tT]ype[sS]cript|^Blockly|^Rules|^FBD/)) emit(doc.common.name, doc); }"
615
615
  }
616
616
  }
617
617
  },
@@ -907,6 +907,30 @@
907
907
  "write": false
908
908
  },
909
909
  "native": {}
910
+ },
911
+ {
912
+ "_id": "debug.fbd",
913
+ "type": "state",
914
+ "common": {
915
+ "name": {
916
+ "en": "Values of a function block diagram for the online view",
917
+ "de": "Werte eines Funktionsplans für die Onlineansicht",
918
+ "ru": "Значения функциональной блок-схемы для онлайн-просмотра",
919
+ "pt": "Valores de um diagrama de blocos funcionais para a vista online",
920
+ "nl": "Waarden van een functieblokdiagram voor de online weergave",
921
+ "fr": "Valeurs d'un diagramme de blocs fonctionnels pour la vue en ligne",
922
+ "it": "Valori di un diagramma a blocchi funzionali per la vista online",
923
+ "es": "Valores de un diagrama de bloques de funciones para la vista en línea",
924
+ "pl": "Wartości diagramu bloków funkcyjnych dla widoku online",
925
+ "uk": "Значення функціональної блок-схеми для онлайн-перегляду",
926
+ "zh-cn": "功能块图在线视图的数值"
927
+ },
928
+ "type": "string",
929
+ "role": "json",
930
+ "read": true,
931
+ "write": false
932
+ },
933
+ "native": {}
910
934
  }
911
935
  ]
912
936
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.javascript",
3
- "version": "10.2.4",
3
+ "version": "10.3.0",
4
4
  "description": "Rules Engine for ioBroker",
5
5
  "author": "bluefox <dogafox@gmail.com>",
6
6
  "contributors": [
@@ -43,14 +43,14 @@
43
43
  "dependencies": {
44
44
  "@iobroker/adapter-core": "^3.4.3",
45
45
  "@iobroker/types": "^7.2.2",
46
- "@types/node": "^22.20.2",
46
+ "@types/node": "^22.20.3",
47
47
  "axios": "^1.20.0",
48
48
  "jsonata": "^2.2.2",
49
49
  "jszip": "^3.10.2",
50
50
  "node-inspect": "^2.0.0",
51
51
  "node-schedule": "2.1.1",
52
- "nodemailer": "^10.0.9",
53
- "prettier": "^3.9.6",
52
+ "nodemailer": "^10.0.10",
53
+ "prettier": "^3.9.7",
54
54
  "semver": "^7.8.5",
55
55
  "suncalc2": "^1.8.1",
56
56
  "typescript": "~6.0.3",
@@ -64,15 +64,15 @@
64
64
  "@iobroker/adapter-dev": "^1.5.0",
65
65
  "@iobroker/build-tools": "^3.0.3",
66
66
  "@iobroker/eslint-config": "^2.3.4",
67
- "@iobroker/plugin-sentry": "^3.2.0",
68
- "@iobroker/testing": "^6.2.1",
67
+ "@iobroker/plugin-sentry": "^3.2.1",
68
+ "@iobroker/testing": "^6.2.2",
69
69
  "@tsconfig/node22": "^22.0.6",
70
70
  "@types/node-schedule": "^2.1.8",
71
- "@types/nodemailer": "^8.0.1",
71
+ "@types/nodemailer": "^8.0.2",
72
72
  "@types/request": "^2.48.13",
73
73
  "@types/suncalc": "^1.9.2",
74
74
  "alcalzone-shared": "^5.0.0",
75
- "jsdom": "^30.0.1",
75
+ "jsdom": "^30.1.0",
76
76
  "timekeeper": "^2.3.1"
77
77
  },
78
78
  "bugs": {
@@ -1,27 +0,0 @@
1
- import{t as e}from"./vite-preload-helper-CaC3yEL3.js";import{$n as t,An as n,Bn as r,Bt as i,Cn as a,Dn as o,En as s,Ht as c,Lt as l,Qn as u,Un as d,Ut as f,Vt as p,Xt as m,Zt as h,_r as g,br as _,bt as v,fr as y,hr as b,kn as x,mn as S,p as C,pn as w,ut as T,vt as E,wr as D,xn as ee,yn as O,yr as k,yt as A,zt as j}from"./_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__113183188387379__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-D-gi6Mty.js";import{S as M,g as te,h as N,m as P,s as F}from"./index-B0FfAYMN.js";import{a as I,c as L,d as R,f as z,h as B,i as V,l as H,m as U,n as W,o as G,p as K,r as ne,s as q,t as J,u as Y}from"./AiChatService-Bsp_rhVx.js";var X=r(u(`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=r(u(`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=r(u(`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=r(u(`path`,{d:`M9.01 14H2v2h7.01v3L13 15l-3.99-4zm5.98-1v-3H22V8h-7.01V5L11 9z`}),`CompareArrows`),oe=r(u(`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=r(u(`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=r(u(`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`);D();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 N(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(t){let{socket:n,runningInstances:r,currentCode:i,currentLanguage:a,allScripts:o,editorApi:s,currentScriptId:c}=t,l=y((e,t,n)=>e===`none`||!n?null:{range:t,scriptId:c||``,scriptVersion:(i||``).length,kind:e,originalText:n},[c,i]),[u,d]=_(()=>{try{let e=window.localStorage.getItem(`Editor.aiChatMessages`);return e?JSON.parse(e):[]}catch{return[]}}),f=y(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]=_(!1),[h,g]=_(null),[v,x]=_(window.localStorage.getItem(`Editor.aiChatMode`)||`agent`),S=y(e=>{x(e),window.localStorage.setItem(`Editor.aiChatMode`,e)},[]),[w,T]=_(null),[E,D]=_(window.localStorage.getItem(`openai-model`)||``),[ee,O]=_([]),[A,j]=_({}),[M,N]=_(!0),[F,I]=_(null),W=k(null),J=k(null),X=k(null),re=k(null),ie=y(e=>{D(e),K(e,A[e])},[A]),ae=y(async()=>{N(!0),I(null);try{let e=await R(n,r);if(O(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),K(n,e.providerMap[n])}e.errors.length>0&&I(e.errors.join(`; `))}catch(e){I(String(e))}N(!1)},[n,r]);b(()=>{ae()},[ae]);let oe=y(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=y(async(e,t,s)=>{re.current||=await H(),W.current||=await G(n,r);let c=Y(),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${q(c)}`),[{role:`system`,content:d}]},[n,r,i,a,o]),ce=y(async e=>{if(!e.trim()||p)return;let t=A[E];if(!t){T(C.t(`Please select a valid model`));return}let i=W.current||await G(n,r);if(W.current=i,!i){T(C.t(`No API keys configured`));return}let o=Object.keys(r)[0];if(!o){T(C.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:`⏳ ${C.t(`Generating plan...`)}`,timestamp:Date.now()};f(e=>[...e,c,l]),m(!0),T(null);try{let r=Y();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 U(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:`📋 **${C.t(`Plan`)}:**\n${u}`}),t});let d={id:Ce(),role:`assistant`,content:`⏳ ${C.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.`,_=p?q(r):L(r),v=await U(n,o,{messages:[{role:`system`,content:_},{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}),g(`${C.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=y(async e=>{if(v===`code`)return ce(e);if(!e.trim()||p)return;let t=A[E];if(!t){T(C.t(`Please select a valid model`));return}let i=W.current||await G(n,r);if(W.current=i,!i){T(C.t(`No API keys configured`));return}let a=Object.keys(r)[0];if(!a){T(C.t(`No running javascript instance found`));return}let c=J.current;if(J.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},_={id:Ce(),role:`assistant`,content:``,timestamp:Date.now(),sourceRange:c};f(e=>[...e,h,_]),m(!0),T(null);let{cleanMessage:y,mentionedScriptIds:b,includeAll:x,includeDevices:S}=oe(e),w=[];if(x)w.push(`${C.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(C.t(`current script`));S&&w.push(C.t(`devices`)),g(`${C.t(`Context`)}: ${w.join(` + `)}`);let D=await se(x,S,b),ee=t===`custom`&&i.gptBaseUrl||``,O=y||e;if(o&&o.length>0){let e=O.match(/\b[\w-]+\.\d+\.[\w.-]+/g);if(e){let t=[];for(let n of new Set(e)){let e=te(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&&(O+=`\n\n[Automatic analysis results]\n${t.join(`
16
-
17
- `)}`)}}let k=[...D,...u.filter(e=>e.role!==`system`).map(e=>({role:e.role,content:e.content})),{role:`user`,content:O}],j=v===`agent`;try{let e=[...k];for(let r=0;r<5;r++){let i=await U(n,a,{messages:e,model:E,provider:t,baseUrl:ee,...j?{tools:le}:{}});if(i.error){if(j&&r===0&&i.error.toLowerCase().includes(`tool`)){let r=await U(n,a,{messages:e,model:E,provider:t,baseUrl:ee});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)&&j&&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`🔍 ${C.t(`Searching datapoints`)}: "${String(t.query||``)}"`;case`get_state_value`:return`📊 ${C.t(`Reading value`)}: ${String(t.id||``)}`;case`get_object_info`:return`📋 ${C.t(`Loading object info`)}: ${String(t.id||``)}`;case`search_scripts`:return`🔍 ${C.t(`Searching scripts`)}: "${String(t.query||``)}"`;case`read_script`:return`📖 ${C.t(`Reading script`)}: ${String(t.id||``)}`;case`list_scripts`:return`📂 ${C.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=y(()=>{f([]),T(null),m(!1),g(null),ne(),window.localStorage.removeItem(`Editor.aiChatHistory`)},[f]),de=y(async(e,t)=>{let i=A[E];if(!i)return`Error: ${C.t(`Please select a valid model`)}`;let o=W.current||await G(n,r);if(W.current=o,!o)return`Error: ${C.t(`No API keys configured`)}`;let s=Object.keys(r)[0];if(!s)return`Error: ${C.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 U(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:ee,modelProviderMap:A,modelsLoading:M,modelsError:F,lastContextInfo:h,mode:v,setMode:S,setModel:ie,sendMessage:Z,triggerAiAction:y(t=>{t.range&&t.code?J.current=l(t.kind||`codelens`,t.range,t.code):J.current=null,e(async()=>{let{buildActionPrompt:e}=await import(`./aiPromptBuilder-aJfHa-eU.js`);return{buildActionPrompt:e}},[],import.meta.url).then(({buildActionPrompt:e})=>{let n=e({action:t.action,code:t.code,language:a||`javascript`,diagnostic:t.diagnostic,question:t.question,rangeLabel:t.rangeLabel});n?Z(n):J.current=null}).catch(()=>{J.current=null,T(C.t(`Failed to build AI action prompt`))})},[Z,a,l]),askInline:de,clearChat:ue,retryLoadModels:ae}}D();var Te=({code:e,language:n,themeType:r,onInsertCode:i,onShowDiff:a,sourceRange:o})=>{let s=k(null);b(()=>{var t;let i=window.monaco;if(!s.current||!(i!=null&&(t=i.editor)!=null&&t.colorize))return;let a=n===`ts`||n===`typescript`?`typescript`:n||`javascript`;i.editor.colorize(e,a,{theme:r===`dark`?`vs-dark`:`vs`}).then(e=>{s.current&&(s.current.innerHTML=e)})},[e,n,r]);let c=y(()=>{navigator.clipboard.writeText(e)},[e]);return t(p,{sx:{position:`relative`,my:1,borderRadius:1,overflow:`hidden`,border:`1px solid`,borderColor:`divider`},children:[t(p,{sx:{display:`flex`,justifyContent:`space-between`,alignItems:`center`,px:1,py:.5,bgcolor:`action.hover`,borderBottom:`1px solid`,borderColor:`divider`},children:[u(p,{sx:{fontSize:`0.75rem`,color:`text.secondary`,textTransform:`uppercase`},children:n||`javascript`}),t(p,{children:[u(j,{title:C.t(`Copy`),children:u(S,{size:`small`,onClick:c,children:u(E,{sx:{fontSize:16}})})}),i&&u(j,{title:C.t(`Insert into editor`),children:u(S,{size:`small`,onClick:()=>i(e),children:u(X,{sx:{fontSize:16}})})}),a&&u(j,{title:C.t(`Show as diff`),children:u(S,{size:`small`,onClick:()=>a(e,o),children:u(ae,{sx:{fontSize:16}})})})]})]}),u(`pre`,{ref:s,style:{margin:0,padding:`8px 12px`,overflow:`auto`,maxHeight:400,fontSize:`13px`,fontFamily:`'Cascadia Code', 'Fira Code', 'Consolas', monospace`,backgroundColor:r===`dark`?`#1e1e1e`:`#f8f8f8`,color:r===`dark`?`#d4d4d4`:`#333`},children:e})]})};D();var Ee=({xml:e})=>{let t=d(),n=k(null),r=k(null),[i,a]=_(60),o=k(!1);return b(()=>{o.current&&(o.current=!1,requestAnimationFrame(()=>{let e=window.Blockly,t=r.current;e&&t&&(e.svgResize(t),t.scrollCenter())}))},[i]),b(()=>{let i=window.Blockly;if(i&&n.current){r.current&&=(r.current.dispose(),null);try{let s=i.inject(n.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:F(t),media:`google-blockly/media/`});r.current=s;let c=e.trim();c.startsWith(`<xml`)||(c=`<xml xmlns="https://developers.google.com/blockly/xml">${c}</xml>`);let l=i.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;i.Xml.domToWorkspace(l,s);let f=s.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=s.getBlocksBoundingBox();if(p){let e=p.bottom-p.top+20,t=Math.max(60,Math.ceil(e));o.current=!0,a(t)}}catch{}return()=>{r.current&&=(r.current.dispose(),null)}}},[e,t]),u(p,{ref:n,sx:{width:`100%`,height:i,minHeight:60,borderRadius:1,overflow:`hidden`,border:`1px solid`,borderColor:`divider`}})};D();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(u(`strong`,{children:i[2]},a++)):i[3]?t.push(u(`em`,{children:i[3]},a++)):i[4]&&t.push(u(`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,n,r){let i=n.palette.mode===`dark`,a=e=>e.trim().replace(/^\||\|$/g,``).split(`|`).map(e=>e.trim()),o=a(e[0]),s=e.slice(2).map(a);return u(p,{sx:{overflowX:`auto`,my:1},children:t(`table`,{style:{borderCollapse:`collapse`,width:`100%`,fontSize:`0.8rem`,color:n.palette.text.primary},children:[u(`thead`,{children:u(`tr`,{children:o.map((e,t)=>u(`th`,{style:{border:`1px solid ${n.palette.divider}`,padding:`6px 10px`,backgroundColor:i?n.palette.grey[800]:n.palette.grey[100],color:n.palette.text.primary,fontWeight:600,textAlign:`left`},children:$(e)},t))})}),u(`tbody`,{children:s.map((e,t)=>u(`tr`,{style:{backgroundColor:t%2==1?i?n.palette.grey[900]:n.palette.grey[50]:void 0},children:e.map((e,t)=>u(`td`,{style:{border:`1px solid ${n.palette.divider}`,padding:`6px 10px`,color:n.palette.text.primary},children:$(e)},t))},t))})]})},r)}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(u(`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(u(`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(u(`ul`,{style:{margin:`4px 0`,paddingLeft:20},children:e.map((e,t)=>u(`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(u(`ol`,{style:{margin:`4px 0`,paddingLeft:20},children:e.map((e,t)=>u(`li`,{children:$(e)},t))},i++));continue}r.push(u(`div`,{children:$(e)},i++)),a++}return r}var Me=({message:e,themeType:r,currentLanguage:i,onInsertCode:a,onShowDiff:o,onApplyCode:s})=>{let l=e.role===`user`,d=c(),m=l?r===`dark`?d.palette.primary.dark:d.palette.primary.main:r===`dark`?d.palette.secondary.dark:d.palette.secondary.main,h=d.palette.getContrastText(m),_=g(()=>De(e.content),[e.content]),v=(e,t)=>!!(e===`xml`||e===`blockly`||i===`blockly`&&t&&/<block\s+type=/.test(t));return t(p,{sx:{display:`flex`,gap:1,px:1.5,py:1,mx:.75,my:.5,bgcolor:l?r===`dark`?`rgba(144, 202, 249, 0.10)`:`rgba(25, 118, 210, 0.07)`:r===`dark`?`rgba(206, 147, 216, 0.10)`:`rgba(156, 39, 176, 0.06)`,borderRadius:1.5,borderLeft:`3px solid`,borderLeftColor:m,transition:`background-color 120ms`,"&:hover":{bgcolor:l?r===`dark`?`rgba(144, 202, 249, 0.16)`:`rgba(25, 118, 210, 0.12)`:r===`dark`?`rgba(206, 147, 216, 0.16)`:`rgba(156, 39, 176, 0.10)`}},children:[u(n,{sx:{width:28,height:28,bgcolor:m,color:h,flexShrink:0,mt:.5},children:u(l?oe:ce,{sx:{fontSize:18}})}),u(p,{sx:{flex:1,minWidth:0,fontSize:`0.875rem`,lineHeight:1.6},children:_.map((n,i)=>n.type===`code`?v(n.language,n.content)?t(p,{sx:{my:1},children:[u(Ee,{xml:n.content}),t(p,{sx:{display:`flex`,gap:.5,mt:.5},children:[s&&u(f,{size:`small`,variant:`contained`,color:`primary`,startIcon:u(se,{sx:{fontSize:14}}),onClick:()=>s(n.content),sx:{textTransform:`none`,fontSize:`0.75rem`},children:C.t(`Apply blocks`)}),a&&u(f,{size:`small`,variant:`outlined`,startIcon:u(X,{sx:{fontSize:14}}),onClick:()=>a(n.content),sx:{textTransform:`none`,fontSize:`0.75rem`},children:C.t(`Insert blocks`)})]})]},i):u(Te,{code:n.content,language:n.language||`javascript`,themeType:r,onInsertCode:a,onShowDiff:o,sourceRange:e.sourceRange||null},i):u(p,{sx:{wordBreak:`break-word`,color:d.palette.text.primary},children:je(n.content,d)},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}D();function Le(){return[{id:`@all`,label:C.t(`mention @all`),descriptionKey:`All scripts`},{id:`@devices`,label:C.t(`mention @devices`),descriptionKey:`Smart home devices`}]}function Re({provider:e,isDark:t}){return W[e]?u(`img`,{src:`./img/${e}.svg`,alt:e,style:{...J,...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:e,disabled:n,themeType:r,hasSelection:c,selectionText:d,allScripts:f,model:h,availableModels:v,modelProviderMap:w,modelsLoading:T,onModelChange:E,mode:D,onModeChange:te,currentLanguage:N})=>{let[P,F]=_(``),[I,L]=_(!1),[R,z]=_(``),[B,V]=_(0),H=k(null),U=k(-1),W=k(ze()),G=k(-1),K=k(``),ne=g(()=>{let e=Le().map(e=>({...e,description:C.t(e.descriptionKey)}));if(f)for(let t of f){let n=t.id.replace(/^script\.js\./,``).replace(/\./g,`/`);e.push({id:`@${n}`,label:`@${n}`,description:`${t.name} [${t.enabled?`active`:`inactive`}]`})}return e},[f]),q=g(()=>{if(!R)return ne;let e=R.toLowerCase();return ne.filter(t=>t.id.toLowerCase().includes(e)||t.description.toLowerCase().includes(e))},[ne,R]);b(()=>{V(0)},[R]);let J=y(()=>{let t=P.trim();if(!t||n)return;let r=t,i=Ie(t);if(i){let e=c&&d?d:``,t=Fe({action:i.action,code:e,language:N||`javascript`,question:i.action===`ask`?i.rest:void 0,diagnostic:i.action===`fix`&&i.rest||void 0});t&&(r=t)}else c&&d&&(r=`[Selected code in editor]\n\`\`\`\n${d}\n\`\`\`\n\n${t}`);W.current.push(t),G.current=-1,K.current=``;try{let e=W.current.slice(-50);window.localStorage.setItem(`Editor.aiChatHistory`,JSON.stringify(e))}catch{}e(r),F(``),L(!1),requestAnimationFrame(()=>{var e;return(e=H.current)==null?void 0:e.focus()})},[P,n,e,c,d,N]),Y=y(e=>{let t=U.current,n=H.current;if(t<0){let t=P?`${P}${e} `:`${e} `;F(t),L(!1),z(``),setTimeout(()=>{n&&(n.focus(),n.setSelectionRange(t.length,t.length))},0);return}let r=P.substring(0,t),i=(n==null?void 0:n.selectionStart)??P.length,a=`${r}${e} ${P.substring(i)}`;F(a),L(!1),z(``),U.current=-1,setTimeout(()=>{if(n){let t=r.length+e.length+1;n.focus(),n.setSelectionRange(t,t)}},0)},[P]),X=y(()=>{U.current=-1,z(``),L(e=>!e)},[]),re=y(e=>{let t=e.target.value;F(t);let n=e.target.selectionStart??t.length,r=t.substring(0,n).match(/@([\w/äöüÄÖÜß]*)$/);r?(U.current=n-r[0].length,z(r[1]),L(!0)):(L(!1),z(``))},[]),ae=y(e=>{if(I&&q.length>0){if(e.key===`ArrowDown`){e.preventDefault(),V(e=>(e+1)%q.length);return}if(e.key===`ArrowUp`){e.preventDefault(),V(e=>(e-1+q.length)%q.length);return}if(e.key===`Enter`||e.key===`Tab`){e.preventDefault(),Y(q[B].id);return}if(e.key===`Escape`){e.preventDefault(),L(!1);return}}if(e.key===`ArrowUp`&&!I&&W.current.length>0){let t=H.current,n=!t||t.selectionStart===0,r=!P.includes(`
26
- `);if(n&&r){e.preventDefault(),G.current===-1?(K.current=P,G.current=W.current.length-1):G.current>0&&G.current--,F(W.current[G.current]);return}}if(e.key===`ArrowDown`&&!I&&G.current>=0){let t=H.current,n=!t||t.selectionStart===P.length,r=!P.includes(`
27
- `);if(n&&r){e.preventDefault(),G.current<W.current.length-1?(G.current++,F(W.current[G.current])):(G.current=-1,F(K.current));return}}e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),J())},[J,I,q,B,Y,P]);return t(p,{sx:{borderTop:`1px solid`,borderColor:`divider`,position:`relative`},children:[I&&q.length>0&&u(o,{elevation:4,sx:{position:`absolute`,bottom:`100%`,left:8,right:8,maxHeight:200,overflow:`auto`,zIndex:10,mb:.5},children:u(O,{dense:!0,disablePadding:!0,children:q.slice(0,15).map((e,t)=>u(ee,{selected:t===B,onClick:()=>Y(e.id),sx:{py:.25,minHeight:32},children:u(a,{primary:e.label,secondary:e.description,slotProps:{primary:{sx:{fontSize:`0.8rem`,fontWeight:500}},secondary:{sx:{fontSize:`0.7rem`}}}})},e.id))})}),D===`code`&&u(m,{label:`${C.t(`mention @devices`)} — ${C.t(`Smart home devices`)}`,size:`small`,variant:`outlined`,sx:{mx:1,mt:.5,maxWidth:`calc(100% - 16px)`}}),c&&d&&u(m,{icon:u(A,{sx:{fontSize:14}}),label:C.t(`Selected code as context`),size:`small`,variant:`outlined`,sx:{mx:1,mt:.5,maxWidth:`calc(100% - 16px)`}}),t(p,{sx:{mx:1,mt:.5,mb:.5,border:`1px solid`,borderColor:`divider`,borderRadius:1.5,overflow:`hidden`,"&:focus-within":{borderColor:`primary.main`}},children:[u(l,{inputRef:H,fullWidth:!0,multiline:!0,maxRows:6,placeholder:C.t(`Ask about your script...`),value:P,onChange:re,onKeyDown:ae,disabled:n,onBlur:()=>{setTimeout(()=>L(!1),200)},variant:`standard`,slotProps:{input:{disableUnderline:!0}},sx:{px:1.5,pt:1,pb:.5,"& .MuiInputBase-root":{fontSize:`0.875rem`}}}),t(p,{sx:{display:`flex`,alignItems:`center`,gap:.75,px:1,pb:.5},children:[u(j,{title:t(p,{sx:{fontSize:`0.8rem`,lineHeight:1.5,maxWidth:360},children:[u(p,{sx:{fontWeight:600,mb:.75},children:C.t(`AI chat mode`)}),t(p,{sx:{mb:.75},children:[t(`strong`,{children:[`💬 `,C.t(`Chat`)]}),` —`,` `,C.t(`Plain conversation. Use for questions, explanations, syntax help. Does not read or modify your scripts.`)]}),t(p,{sx:{mb:.75},children:[t(`strong`,{children:[`🤖 `,C.t(`Agent`)]}),` —`,` `,C.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".`)]}),t(p,{children:[t(`strong`,{children:[`💻 `,C.t(`Code`)]}),` —`,` `,C.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:t(x,{value:D,onChange:e=>te(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:[u(s,{value:`chat`,sx:{fontSize:`0.75rem`},title:C.t(`Plain conversation. Best for: general questions, syntax help, concept explanations.`),children:`💬 Chat`}),u(s,{value:`agent`,sx:{fontSize:`0.75rem`},title:C.t(`For larger models with tool support. Best for: creating, editing, or analyzing scripts; finding datapoint usages; inspecting the object tree.`),children:`🤖 Agent`}),u(s,{value:`code`,sx:{fontSize:`0.75rem`},title:C.t(`For smaller models without tool support. Best for: creating new JavaScript/TypeScript or Blockly scripts from a description.`),children:`💻 Code`})]})}),u(x,{value:h,onChange:e=>E(e.target.value),size:`small`,disabled:T||v.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:v.map(e=>t(s,{value:e,sx:{fontSize:`0.75rem`,display:`flex`,gap:.5},children:[u(Re,{provider:w[e],isDark:r===`dark`}),e]},e))}),u(j,{title:C.t(`Mention scripts as context for the AI. Use @all for all scripts or @scriptName for a specific one.`),enterDelay:500,children:u(S,{size:`small`,onClick:X,sx:{p:`3px`,color:I?`primary.main`:`text.secondary`,border:`1px solid`,borderColor:I?`primary.main`:`text.secondary`,bgcolor:I?void 0:`action.hover`,borderRadius:3,"&:hover":{borderColor:`text.disabled`,bgcolor:`action.hover`}},children:u(ie,{sx:{fontSize:16}})})}),u(p,{sx:{flex:1}}),t(i,{variant:`caption`,sx:{color:`text.disabled`,fontSize:`0.65rem`,mr:.5,whiteSpace:`nowrap`},children:[`Enter `,C.t(`to send`)]}),u(j,{title:`${C.t(`Send`)} (Enter)`,children:u(`span`,{children:u(S,{color:`primary`,onClick:J,disabled:n||!P.trim(),size:`small`,sx:{p:.25},children:u(M,{sx:{fontSize:18}})})})})]})]})]})};D();var Ve=({socket:e,runningInstances:n,themeType:r,currentCode:a,currentLanguage:o,selectedCode:s,allScripts:c,editorApi:l,aiActionRequest:d,onAiActionConsumed:f,onRegisterInlineAsk:m,onInsertCode:_,onShowDiff:x,onApplyCode:E,currentScriptId:D,onClose:ee})=>{var O;let A=k(null),{messages:M,isLoading:te,error:N,model:P,availableModels:F,modelProviderMap:I,modelsLoading:L,modelsError:R,lastContextInfo:z,mode:B,setMode:V,setModel:H,sendMessage:U,triggerAiAction:W,askInline:G,clearChat:K,retryLoadModels:ne}=we(g(()=>({socket:e,runningInstances:n,currentCode:a,currentLanguage:o,allScripts:c,editorApi:l,currentScriptId:D}),[e,n,a,o,c,l,D]));b(()=>(m==null||m(G),()=>m==null?void 0:m(null)),[G,m]);let q=k(null);b(()=>{d&&q.current!==d&&(q.current=d,W(d),f==null||f())},[d,W,f]),b(()=>{var e;(e=A.current)==null||e.scrollIntoView({behavior:`smooth`})},[M]);let J=y(e=>{_==null||_(e)},[_]),Y=y((e,t)=>{x==null||x(e,t)},[x]),X=y(e=>{E==null||E(e)},[E]);return t(p,{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:[t(p,{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:[u(i,{variant:`subtitle2`,sx:{fontWeight:600,flex:1,color:`text.primary`},children:C.t(`AI Chat`)}),L&&u(h,{size:16}),u(j,{title:C.t(`New chat`),children:u(S,{size:`small`,onClick:K,children:u(re,{sx:{fontSize:18}})})}),u(j,{title:C.t(`Close`),children:u(S,{size:`small`,onClick:ee,children:u(v,{sx:{fontSize:18}})})})]}),(N||R)&&u(w,{severity:`error`,sx:{m:1,py:0},action:R?u(S,{size:`small`,onClick:ne,children:u(T,{sx:{fontSize:16}})}):void 0,children:N||R}),z&&u(i,{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:z}),t(p,{sx:{flex:1,overflow:`auto`,py:1},children:[M.length===0&&!te&&t(p,{sx:{display:`flex`,flexDirection:`column`,alignItems:`center`,justifyContent:`center`,height:`100%`,color:`text.secondary`,px:3,textAlign:`center`},children:[u(i,{variant:`body2`,sx:{mb:1},children:C.t(`Ask questions about your script, request changes, or generate new code.`)}),t(i,{variant:`caption`,color:`text.disabled`,children:[`Enter `,C.t(`to send`),`, Shift+Enter `,C.t(`for new line`)]})]}),M.filter(e=>e.role!==`system`).map(e=>u(Me,{message:e,themeType:r,currentLanguage:o,onInsertCode:J,onShowDiff:Y,onApplyCode:X},e.id)),te&&((O=M[M.length-1])==null?void 0:O.content)===``&&t(p,{sx:{display:`flex`,alignItems:`center`,gap:1,px:2,py:1},children:[u(h,{size:16}),u(i,{variant:`caption`,color:`text.secondary`,children:C.t(`Thinking...`)})]}),u(`div`,{ref:A})]}),u(Be,{onSend:U,disabled:te||F.length===0,themeType:r,hasSelection:!!s,selectionText:s,allScripts:c,model:P,availableModels:F,modelProviderMap:I,modelsLoading:L,onModelChange:H,mode:B,onModeChange:V,currentLanguage:o})]})};export{Ve as default,Ie as n,Fe as t};
@@ -1 +0,0 @@
1
- import{$n as e,Bt as t,Qn as n,Rt as r,St as i,Ut as a,Vt as o,bt as s,fr as c,hr as l,p as u,wr as d,yr as f}from"./_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__113183188387379__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-D-gi6Mty.js";d();var p=({originalCode:d,modifiedCode:p,language:m,themeType:h,onAccept:g,onReject:_})=>{let v=f(null),y=f(null),b=f(null);l(()=>{let e=window.monaco;if(!e||!v.current)return;let t=e.editor.createDiffEditor(v.current,{readOnly:!1,originalEditable:!1,renderSideBySide:!0,automaticLayout:!0,theme:h===`dark`?`vs-dark`:`vs`,scrollBeyondLastLine:!1,minimap:{enabled:!1}}),n=e.editor.createModel(d,m),r=e.editor.createModel(p,m);return b.current=r,t.setModel({original:n,modified:r}),y.current=t,()=>{t.dispose(),n.dispose(),r.dispose(),y.current=null,b.current=null}},[d,p,m,h]);let x=c(()=>{var e;g(((e=b.current)==null?void 0:e.getValue())||p)},[p,g]);return e(o,{sx:{display:`flex`,flexDirection:`column`,height:`100%`,width:`100%`},children:[e(r,{variant:`dense`,sx:{minHeight:36,bgcolor:`background.paper`,borderBottom:`1px solid`,borderColor:`divider`,gap:1,flexShrink:0},children:[n(t,{variant:`subtitle2`,sx:{flex:1},children:u.t(`AI suggested changes`)}),n(a,{variant:`contained`,color:`success`,size:`small`,startIcon:n(i,{}),onClick:x,children:u.t(`Accept`)}),n(a,{variant:`outlined`,color:`error`,size:`small`,startIcon:n(s,{}),onClick:_,children:u.t(`Reject`)})]}),n(o,{ref:v,sx:{flex:1,overflow:`hidden`}})]})};export{p as default};