iobroker.javascript 10.3.0 → 10.4.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.
- package/README.md +20 -9
- package/admin/assets/AiChatPanel-BjRIKaXG.js +27 -0
- package/admin/assets/{AiChatService-QKcpW4jQ.js → AiChatService-DP1EmVk2.js} +3 -3
- package/admin/assets/AiDiffView-DeynDw7L.js +1 -0
- package/admin/assets/{AiInlineProvider-DTSPKoXG.js → AiInlineProvider-jkEIJJJ-.js} +1 -1
- package/admin/assets/{BlocklyEditor-BZyoN1JE.js → BlocklyEditor-DhwThchX.js} +7 -7
- package/admin/assets/Compile-e8N5zI-J.js +165 -0
- package/admin/assets/Debugger-BDQUKM1K.js +15 -0
- package/admin/assets/Diff--plofAtP.js +1 -0
- package/admin/assets/{Documentation-uz4Ut9pT.js → Documentation-D3E0U4AK.js} +4 -4
- package/admin/assets/ExpandMore-Dio4GeHC.js +1 -0
- package/admin/assets/{FbEditor-aOZ-RpPV.js → FbEditor-BjLPNzpK.js} +6 -6
- package/admin/assets/History-Ewi5YEEn.js +1 -0
- package/admin/assets/Import-6Mm2vrM2.js +1 -0
- package/admin/assets/MonacoDiff-BYvG7IqB.js +1 -0
- package/admin/assets/{NotificationsActive-BdzH44gp.js → NotificationsActive-CuNfWVJM.js} +1 -1
- package/admin/assets/RulesEditor--YX6ETsU.js +1 -0
- package/admin/assets/{ScriptEditor-CviB6Hif.js → ScriptEditor-BadPC8Mf.js} +2 -2
- package/admin/assets/ScriptEditorVanillaMonaco-BnAmy59d.js +3 -0
- package/admin/assets/Send-Pz1eveU5.js +1 -0
- package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-Ceh8EDcF.js +1 -0
- package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__234968779812303__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BRdHvuuG.js +1217 -0
- package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__234968779812303__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DLWT3PGo.js +9 -0
- package/admin/assets/aiPromptBuilder-Co6AqZwx.js +1 -0
- package/admin/assets/{blockly-fcfyKYzp.js → blockly-B0t_IRJQ.js} +1 -1
- package/admin/assets/{blocklyTheme-CGhU3cEO.js → blocklyTheme-iZoge1S9.js} +1 -1
- package/admin/assets/{blocks_action-BQ4O7NRE.js → blocks_action-Ctn5A1AU.js} +1 -1
- package/admin/assets/{blocks_convert-0VBjfhqQ.js → blocks_convert-BI0lf0sf.js} +1 -1
- package/admin/assets/{blocks_logic-DAo99xDr.js → blocks_logic-o49klUX_.js} +1 -1
- package/admin/assets/{blocks_number-C--e19NU.js → blocks_number-DZtyWFyR.js} +1 -1
- package/admin/assets/{blocks_object-D0TPhdzg.js → blocks_object-BuzGCxVr.js} +1 -1
- package/admin/assets/blocks_procedures-jn9sIYmR.js +3 -0
- package/admin/assets/{blocks_sendto-CRIrtOUc.js → blocks_sendto-Coui8w1H.js} +2 -2
- package/admin/assets/{blocks_switch-b_GYfF0n.js → blocks_switch-CeRZizTM.js} +1 -1
- package/admin/assets/{blocks_system-BdkUdSsc.js → blocks_system-CaBPIC40.js} +1 -1
- package/admin/assets/{blocks_text-DSFhEVOf.js → blocks_text-DeDtPYWf.js} +1 -1
- package/admin/assets/{blocks_time-CqALAiJp.js → blocks_time-CTXQH3Lm.js} +1 -1
- package/admin/assets/{blocks_timeout-yrOD2pZp.js → blocks_timeout-D8IOKOb-.js} +1 -1
- package/admin/assets/{blocks_trigger-DeAYXpSS.js → blocks_trigger-zuuXJbhb.js} +2 -2
- package/admin/assets/{cronHoverProvider-DoO2_tpG.js → cronHoverProvider-Curcjz4m.js} +1 -1
- package/admin/assets/dist-CzitsFi7.js +1 -0
- package/admin/assets/field_cron-RgLY53_S.js +1 -0
- package/admin/assets/field_oid-rBhotXJe.js +1 -0
- package/admin/assets/field_script-CU7g3-oB.js +1 -0
- package/admin/assets/helpers-BZgjFQNf.js +1 -0
- package/admin/assets/{helpers-BTGaTdnT.js → helpers-BwllSRzJ.js} +1 -1
- package/admin/assets/hostInit-CrHjJGJJ.js +1 -0
- package/admin/assets/index-Bmmscq2G.js +157 -0
- package/admin/assets/{inlineChatWidget-BwQVCPkx.js → inlineChatWidget-ChchJD9a.js} +1 -1
- package/admin/assets/{inlineDiffController-BsDDsDHn.js → inlineDiffController-ly6qX4jk.js} +1 -1
- package/admin/assets/{loadBlocks-RpqM7PwO.js → loadBlocks-BcFtthDb.js} +23 -23
- package/admin/assets/{mf-entry-bootstrap-0-0deef484.js → mf-entry-bootstrap-0-6db6c4fc.js} +3 -3
- package/admin/assets/pendingShares-mBGPbRwZ.js +2 -0
- package/admin/assets/{reactour.esm-DX9ZgYlx.js → reactour.esm-Dk3aGxKn.js} +5 -5
- package/admin/assets/{stateHoverProvider-BEadnSXp.js → stateHoverProvider-wAsP-THx.js} +1 -1
- package/admin/assets/utils-DUKzLJUz.js +4 -0
- package/admin/assets/vite-preload-helper-DjNwdemH.js +1 -0
- package/admin/custom/assets/Components-fDcxCyN4.js +1 -0
- package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-BraOrMSu.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-DbKT6Hsb.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-CVvbIPAy.js +1 -0
- package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DVb0ZZ1Q.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BhZYie9-.js} +89 -89
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.js-CV50dgj4.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__date_mf_2_fns__loadShare__.js-Djg9OMcQ.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__leaflet__loadShare__.js-D9EyCd42.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__shared-Hb6V6BnJ.js +2 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-BrY-nF2a.js +122 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild__leaflet__prebuild__-CHjWtrkp.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild__react_mf_2_dom_mf_1_client__prebuild__-DOkC-g0X.js +9 -0
- package/admin/custom/assets/dist-CzitsFi7.js +1 -0
- package/admin/custom/assets/helpers-BZgjFQNf.js +1 -0
- package/admin/custom/assets/hostInit-akwaQLq8.js +1 -0
- package/admin/custom/assets/index-BkItz-nL.js +1 -0
- package/admin/custom/assets/{lib-BmDlTzq2.js → lib-CADOx2YN.js} +1 -1
- package/admin/custom/assets/{mf-entry-bootstrap-0-ad1cd7d0.js → mf-entry-bootstrap-0-3c4565e0.js} +3 -3
- package/admin/custom/assets/pendingShares-TCMDgBLn.js +2 -0
- package/admin/custom/assets/utils-DUKzLJUz.js +4 -0
- package/admin/custom/assets/vite-preload-helper-DjNwdemH.js +1 -0
- package/admin/custom/customComponents.js +2 -2
- package/admin/custom/i18n/de.json +19 -1
- package/admin/custom/i18n/en.json +19 -1
- package/admin/custom/i18n/es.json +19 -1
- package/admin/custom/i18n/fr.json +19 -1
- package/admin/custom/i18n/it.json +19 -1
- package/admin/custom/i18n/nl.json +19 -1
- package/admin/custom/i18n/pl.json +19 -1
- package/admin/custom/i18n/pt.json +19 -1
- package/admin/custom/i18n/ru.json +19 -1
- package/admin/custom/i18n/uk.json +19 -1
- package/admin/custom/i18n/zh-cn.json +19 -1
- package/admin/i18n/de.json +13 -1
- package/admin/i18n/en.json +13 -1
- package/admin/i18n/es.json +13 -1
- package/admin/i18n/fr.json +13 -1
- package/admin/i18n/it.json +13 -1
- package/admin/i18n/nl.json +13 -1
- package/admin/i18n/pl.json +13 -1
- package/admin/i18n/pt.json +13 -1
- package/admin/i18n/ru.json +13 -1
- package/admin/i18n/uk.json +13 -1
- package/admin/i18n/zh-cn.json +13 -1
- package/admin/jsonConfig.json +274 -86
- package/admin/mf-manifest.json +1 -1
- package/admin/mf-stats.json +1 -1
- package/admin/remoteEntry.js +2 -2
- package/admin/tab.html +2 -2
- package/build/lib/aiProviderResolver.js +145 -25
- package/build/lib/aiProviderResolver.js.map +1 -1
- package/build/lib/anthropicAdapter.js +37 -0
- package/build/lib/anthropicAdapter.js.map +1 -1
- package/build/lib/inspect.js +66 -10
- package/build/lib/inspect.js.map +1 -1
- package/build/lib/mirror.js +24 -23
- package/build/lib/mirror.js.map +1 -1
- package/build/lib/scriptHistory.js +245 -0
- package/build/lib/scriptHistory.js.map +1 -0
- package/build/main.js +575 -31
- package/build/main.js.map +1 -1
- package/build/types.d.ts +11 -0
- package/io-package.json +17 -15
- package/package.json +7 -7
- package/admin/assets/AiChatPanel-CpY4Bun-.js +0 -27
- package/admin/assets/AiDiffView-DscPfZ38.js +0 -1
- package/admin/assets/Compile-Oss28m_f.js +0 -165
- package/admin/assets/Debugger-teJTIU-2.js +0 -15
- package/admin/assets/ExpandMore-V5Ix1QB1.js +0 -1
- package/admin/assets/Import-BIC5Ee9z.js +0 -1
- package/admin/assets/RulesEditor-CcDVthPa.js +0 -1
- package/admin/assets/ScriptEditorVanillaMonaco-ByuXwybM.js +0 -3
- package/admin/assets/Send-Mdo32jMb.js +0 -1
- package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-BnL93BgK.js +0 -1
- package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-NI-3Uv4e.js +0 -1217
- package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DVaMIZyC.js +0 -9
- package/admin/assets/aiPromptBuilder-yTB6N2VT.js +0 -1
- package/admin/assets/blocks_procedures-DgTxgXdB.js +0 -3
- package/admin/assets/dist-D4uJqRBO.js +0 -4
- package/admin/assets/field_cron-D3Ts_s9M.js +0 -1
- package/admin/assets/field_oid-BRNXredg.js +0 -1
- package/admin/assets/field_script-3X6ousg7.js +0 -1
- package/admin/assets/hostInit-2h2Cbsaw.js +0 -1
- package/admin/assets/index-CbQlIKB_.js +0 -156
- package/admin/assets/pendingShares-BaAadIDv.js +0 -1
- package/admin/assets/vite-preload-helper-CaC3yEL3.js +0 -1
- package/admin/custom/assets/Components-FkGDIlId.js +0 -1
- package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-Cs88NUCd.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-P-8ffWXw.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-ZVuRAEo5.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-Dna3WF04.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare___mf_0_mui_mf_1_x_mf_2_date_mf_2_pickers__loadShare__.js-DcjdCGAx.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__date_mf_2_fns__loadShare__.js-CnhNjamd.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__leaflet__loadShare__.js-Dz7BFJqH.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-B0olko2J.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-CzN4reh_.js +0 -122
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__leaflet__prebuild__-xPcBaiTQ.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__react_mf_2_dom_mf_1_client__prebuild__-DuFBE5fh.js +0 -9
- package/admin/custom/assets/dist-D4uJqRBO.js +0 -4
- package/admin/custom/assets/hostInit-6oh4UY2k.js +0 -1
- package/admin/custom/assets/index-BrlyEy6J.js +0 -1
- package/admin/custom/assets/pendingShares-kV2kwejX.js +0 -1
- package/admin/custom/assets/vite-preload-helper-CaC3yEL3.js +0 -1
- /package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-CXpyx8Vy.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-CXpyx8Vy.js} +0 -0
package/build/types.d.ts
CHANGED
|
@@ -55,6 +55,17 @@ export interface JavaScriptAdapterConfig {
|
|
|
55
55
|
* at all and the endpoint decides - which is what a reasoning model behind a proxy wants.
|
|
56
56
|
*/
|
|
57
57
|
aiReasoningEffort?: '' | 'none' | 'minimal' | 'low' | 'medium' | 'high';
|
|
58
|
+
/**
|
|
59
|
+
* Upper bound for the answer of an Anthropic model, in tokens. Anthropic requires the field, so
|
|
60
|
+
* unlike the other providers it cannot be left to the endpoint. 8192 fits every model Anthropic
|
|
61
|
+
* currently offers; the newer ones go far beyond that, which is why this is a setting.
|
|
62
|
+
*/
|
|
63
|
+
aiMaxTokens?: number;
|
|
64
|
+
/**
|
|
65
|
+
* How many saved versions of a script to keep in the file area of the instance.
|
|
66
|
+
* `0` switches the history off.
|
|
67
|
+
*/
|
|
68
|
+
historyVersions?: number;
|
|
58
69
|
claudeKey: string;
|
|
59
70
|
geminiKey: string;
|
|
60
71
|
deepseekKey: string;
|
package/io-package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "javascript",
|
|
4
|
-
"version": "10.
|
|
4
|
+
"version": "10.4.0",
|
|
5
5
|
"blockedVersions": [
|
|
6
6
|
"8.0.0",
|
|
7
7
|
"8.0.1"
|
|
@@ -40,6 +40,19 @@
|
|
|
40
40
|
"Matthias Kleine <info@haus-automatisierung.com>"
|
|
41
41
|
],
|
|
42
42
|
"news": {
|
|
43
|
+
"10.4.0": {
|
|
44
|
+
"en": "The endpoint of an AI request comes out of the configuration and no longer out of the request. An address in the message used to win over the stored one, which was the comfortable way to put a proxy in front of OpenAI - and at the same time the way to have this instance carry the stored key, as the `Authorization` of that request, to an address of somebody else's choosing. Whoever may send a message to this instance could do that. A proxy belongs in the configuration now, where it is entered once by whoever may configure the adapter. The editor never sent an address, so nothing changes for it; the Test buttons of the settings dialog keep trying what stands in the form, with one limit: an address out of the form counts only together with a key out of the form - one's own key to one's own endpoint gives nothing away. In the credential-store mode the saved address is used, so an endpoint of one's own has to be saved before it can be tested there\nOnly an entry that was stored as an AI credential is read from the central credential store. The store holds the secrets of the whole system - a database password, the login of a camera - and a request for \"the key of this provider\" could name any one of them\nThe `execute` message - which runs a script here, with the whole ioBroker API behind it - checks who asked for it. A message never said on whose behalf it came, so there was nothing to check, and everyone who may send one to this instance could have code executed. Where the js-controller names the user (7.2.5 and newer, which put the user of a socket connection into the message), that user needs the right that a command on the host needs. Where it does not name one - an older controller, a script, an adapter - nothing changes\nThe question before a debug session (\"The script will be stopped and must be activated manually after debugging\") started the debugging even when it was answered with \"Cancel\" (#2382)\nStopping a debug session could end the debugged process with \"uncaught exception: write EPIPE\": the inspector process exited at once, although the process it debugs writes its whole log through its pipes and was still shutting down. The inspector now stops that process first and waits till it is really gone, a broken pipe cannot end a debugged script anymore, and the reset of the connection to the debugged process is not reported as an internal error of the inspector (#2382)\nThe AI chat stayed empty when a request took longer than 30 seconds: the answer is pushed as an instance message now instead of waiting for the socket callback\nAn AI answer without content now says why (stop reason, token counts) instead of leaving an empty chat bubble, and every failed request is logged\nAn answer cut off at the output limit is marked as incomplete\nSorted the scripts in the `@` list of the AI chat by their path\nThe AI chat can be maximized to the whole editor area (#2389)\nThe AI chat shows a spinner for the whole request, not only until the first tool call\nFixed an accepted AI suggestion not reaching the visible editor\nFixed the splitters jumping back to their previous width while being dragged\nBlockly: fixed a parameter of a \"JavaScript function\" with its default name making the script unsavable\nAdded a script history: saved versions can be listed, compared and restored in the editor. \"Saved versions per script\" (30 by default, 0 switches it off)\nAdded a \"Script history\" tab with the used storage per script and buttons to delete single, orphaned or all histories\nMoved the credentials table to its own tab\nMirror: a changed file no longer resets `enabled` and `engine` of the script (#2396)",
|
|
45
|
+
"de": "Der Endpunkt einer KI-Anfrage kommt aus der Konfiguration und nicht mehr aus der Anfrage. Eine Adresse in der Nachricht überwog die gespeicherte, was die bequeme Art war, einen Proxy vor OpenAI zu platzieren und gleichzeitig den gespeicherten Schlüssel als `Autorisierung` der Anfrage an eine andere Adresse weiterzuleiten. Wer dieser Instanz eine Nachricht sendet, kann das tun. Ein Proxy gehört jetzt in die Konfiguration. Jeder, der den Adapter konfiguriert, gibt ihn ein. Der Editor hat nie eine Adresse gesendet, also ändert sich daran nichts. Die Testschaltflächen im Einstellungsdialog versuchen immer, was im Formular steht, mit einem Limit: Eine Adresse aus dem Formular zählt nur zusammen — der eigene Schlüssel zum eigenen Endpunkt verrät nichts. Im Credential-Store-Modus wird die Adresse verwendet, also muss ein eigener Endpunkt gespeichert werden\nNur ein KI-Eintrag wird aus dem zentralen Anmeldespeicher gelesen. Der Laden hat das ganze System — Datenbank-Passwort, Kamera-Login — und eine Anfrage nach dem Providerschlüssel könnte jeden nennen\nDie `execute`-Meldung, die hier ein Skript mit der ganzen ioBroker-API ausführt, prüft, wer danach gefragt hat. Eine Nachricht sagte nie, in wessen Namen sie kam, also gab es nichts zu prüfen, und jeder, der eine an diese Instanz sendet, konnte Code ausführen. Wenn der JS-Controller den Benutzer benennt (7.2.5 und neuer, was den Socket-Benutzer in die Nachricht einfügt), benötigt er das Recht, das ein Befehl auf dem Host benötigt. Wo es keinen nennt — ein älterer Controller, ein Script, ein Adapter — ändert sich nichts\nDie Frage vor einer Debug-Sitzung („Das Script wird gestoppt und muss danach manuell aktiviert werden“) begann das Debuggen, auch wenn es mit „Abbrechen“ beantwortet wurde (#2382)\nDas Beenden einer Debug-Sitzung könnte den Debugvorgang mit „uncaught exception: write EPIPE“ beenden: Der Inspector-Prozess wurde sofort beendet, obwohl er sein ganzes Log durchläuft und trotzdem heruntergefahren wird. Der Inspector stoppt den Prozess jetzt zuerst und wartet, bis er wirklich weg ist. Eine kaputte Leitung kann ein Debug-Skript nicht mehr beenden und das Zurücksetzen der Verbindung wird nicht als interner Fehler gemeldet (#2382)\nDer KI-Chat blieb leer, wenn eine Anfrage länger als 30 Sekunden dauerte: Die Antwort wird als Instanznachricht gesendet, statt auf den Socket-Rückruf zu warten\nEine KI-Antwort ohne Inhalt sagt nun warum (Grund, Token zählen), statt eine leere Chatblase, und jede Anfrage wird geloggt\nEine Antwort am Ausgabelimit gilt als unvollständig\nSortierte die Skripte in der `@`-Liste des KI-Chats\nDer KI-Chat ist auf den ganzen Editor maximierbar (#2389)\nDer KI-Chat zeigt die gesamte Anfrage an, nicht nur bis zum ersten Tool-Aufruf\nEin AI-Vorschlag kam nicht im sichtbaren Editor an\nFehler behoben, bei dem die Splitter beim Ziehen wieder breit wurden\nBlockly: Der Standardname einer JavaScript-Funktion machte das Skript unspeicherbar\nSkriptverlauf hinzugefügt: Gespeicherte Versionen im Editor anzeigen „Gespeicherte Versionen pro Skript“ (30, 0 schaltet ab)\nReiter „Skriptverlauf“ mit Speicherplatz pro Script und Buttons zum Löschen einzelner oder aller Historien hinzugefügt\nDie Anmeldeinformationen in ein eigenes Tab verschoben\nMirror: Eine geänderte Datei setzt „Enabled“ und „Engine“ nicht mehr zurück (#2396)",
|
|
46
|
+
"ru": "Конечная точка запроса AI выходит из конфигурации и больше не входит в запрос. Раньше адрес, указанный в сообщении, выигрывал над сохраненным, что было удобнее поставить прокси-сервер перед OpenAI, и в то же время этот экземпляр передавал сохраненный ключ в виде «Авторизации» этого запроса на чужой адрес. Это мог сделать тот, кто может отправить сообщение в этот инстанс. Теперь в конфигурацию входит прокси-сервер, в который каждый, кто может настроить адаптер, вводится один раз. Редактор так и не прислал адрес, поэтому ничего не изменилось. Кнопки «Тестирование» в диалоговом окне настроек продолжают пересматривать то, что написано в форме, но только одно: адрес, не указанный в форме, засчитывается только вместе с ключом, вышедшим из формы, — собственный ключ к конечной точке ничего не даст. В режиме хранилища учетных данных используется сохраненный адрес, поэтому перед тестированием необходимо сохранить собственную конечную точку\nИз центрального хранилища учетных данных считывается только запись, которая была сохранена в качестве учетных данных AI. В хранилище хранятся секреты всей системы — пароль к базе данных, логин камеры — и любой из них может быть назван запрос на получение «ключа этого провайдера»\nСообщение `execute`, которое запускает здесь скрипт, за которым стоит весь API IOBroker, проверяет, кто его запросил. В сообщении так и не было указано, от чьего имени оно пришло, поэтому проверять было нечего, и каждый, кто отправит сообщение в этот экземпляр, мог выполнить код. Если js-controller вводит имя пользователя (версия 7.2.5 и более поздняя версия, в которой в сообщении указано имя пользователя, подключенного к сокету), этому пользователю нужны права, необходимые команде на хосте. Там, где имя не указано — старый контроллер, скрипт, адаптер — ничего не меняется\nВопрос перед сеансом отладки («Скрипт будет остановлен и должен быть активирован вручную после отладки») запустил отладку, даже если на него был дан ответ «Отмена» (#2382)\nОстановка сеанса отладки может привести к завершению отлаженного процесса с появлением «необнаруженного исключения: запись EPIPE»: процесс инспектора сразу же завершился, хотя отлаживаемый процесс записывает весь журнал по каналам и все равно завершается. Теперь инспектор сначала останавливает этот процесс и дожидается его полного завершения, сломанный канал больше не может завершить отлаженный скрипт, а сброс соединения с отлаженным процессом не считается внутренней ошибкой инспектора (#2382)\nЧат с искусственным интеллектом оставался пустым, если запрос длился более 30 секунд: теперь ответ отправляется в виде сообщения экземпляра, а не в ожидании обратного вызова сокета\nТеперь ответ на запрос с помощью искусственного интеллекта, не содержащий информации (причина остановки, количество токенов), вместо того чтобы оставлять пустое окно чата, и каждый неудачный запрос регистрируется в журнале\nОтвет, вырезанный по выходному пределу, помечается как неполный\nСкрипты в списке «@» чата с искусственным интеллектом отсортированы по пути\nЧат с искусственным интеллектом можно максимально использовать для всей области редактора (#2389)\nЧат с искусственным интеллектом показывает, как обрабатывается весь запрос, а не только до первого вызова инструмента\nИсправлено, что принятое предложение об искусственном интеллекте не попадало в видимый редактор\nИсправлена ошибка, из-за которой разделители возвращались к прежней ширине при перетаскивании\nBlockly: исправлен параметр «функции JavaScript» с именем по умолчанию, делающий скрипт недоступным для сохранения\nДобавлена история сценариев: сохраненные версии можно перечислять, сравнивать и восстанавливать в редакторе. «Сохраненные версии для каждого скрипта» (по умолчанию 30, 0 отключает)\nДобавлена вкладка «История сценариев» с объемом используемого хранилища для каждого скрипта и кнопками для удаления отдельных, потерянных или всех историй\nПереместил таблицу учетных данных на отдельную вкладку\nЗеркало: измененный файл больше не перезагружает `enabled` и `engine` скрипта (#2396)",
|
|
47
|
+
"pt": "O endpoint de uma solicitação de IA sai da configuração e não mais da solicitação. Um endereço na mensagem era usado para vencer o armazenado, que era a forma cômoda de colocar um proxy na frente do OpenAI — e de fazer com que essa instância levasse a chave armazenada, como a “Autorização” do pedido, para um endereço escolhido por outra pessoa. Quem mandar uma mensagem a essa instância pode. Um proxy pertence à configuração agora, onde é inserido uma vez por quem configura o adaptador. O editor nunca enviou um endereço, então nada muda; os botões de teste da caixa de diálogo de configurações testam o que está no formulário, com um limite: um endereço fora do formulário só conta junto com uma chave fora do formulário. No modo de armazenamento de credenciais, o endereço salvo é usado, então um endpoint próprio deve ser salvo antes de testá-lo.\nSomente uma entrada armazenada como credencial de IA é lida no repositório central. A loja guarda os segredos de todo o sistema - senha do banco de dados, login da câmera - e um pedido de “chave desse provedor” pode citar qualquer um deles\nA mensagem `execute` - que executa um script aqui, com toda a API IOBroker - verifica quem a pediu. A mensagem nunca dizia de quem veio, então não havia nada a verificar e todo mundo que enviasse uma para essa instância poderia executar o código. Quando o js-controller nomeia o usuário (7.2.5 e versões mais recentes, que incluem uma conexão de soquete na mensagem), ele precisa dos direitos de um comando no host. Onde não se cita um - um controle antigo, um script, um adaptador - nada muda\nA pergunta antes da sessão de depuração (“O script será interrompido e deve ser ativado manualmente após a depuração”) iniciava a depuração mesmo com “Cancelar” (#2382)\nInterromper uma sessão de depuração pode encerrar o processo depurado com “exceção não detectada: escreva EPIPE”: o processo do inspetor saiu de uma vez, embora ele grave todo o log e continue sendo encerrado. O inspetor agora interrompe o processo primeiro e espera até que ele acabe. Um cano quebrado não pode mais encerrar um script depurado e a reinicialização da conexão não é relatada como um erro interno do inspetor (#2382)\nO chat de IA ficava vazio quando uma solicitação demorava mais de 30 segundos: a resposta agora é enviada em vez de esperar pelo soquete\nUma resposta de IA sem conteúdo agora diz o porquê (motivo, token conta) em vez de deixar um balão vazio, e cada falha é registrada\nUma resposta cortada no limite de saída é incompleta\nOrdenou os scripts na lista `@` do chat de IA por caminho\nO chat de IA pode ser usado em todo o editor (#2389)\nO chat de IA mostra toda a solicitação, não só até a primeira chamada\nCorrigimos uma sugestão de IA aceita que não chegava ao editor\nCorrigido o retorno dos divisores à largura anterior ao ser arrastado\nBlockly: corrigiu o parâmetro de uma “função JavaScript” com o nome padrão e o script não salvo\nHistórico do script: versões salvas podem ser listadas, comparadas e restauradas no editor. “Versões salvas por script” (30 por padrão, 0 desliga)\nFoi adicionada a aba “Histórico de scripts” com botões para excluir histórias únicas, órfãs ou todas\nMudou a tabela de credenciais para sua aba\nMirror: um arquivo alterado não reinicia mais o script (#2396)",
|
|
48
|
+
"nl": "Het eindpunt van een AI-verzoek komt voort uit de configuratie en niet meer uit de aanvraag. Een adres in het bericht dat werd gebruikt om het opgeslagen adres te winnen, wat de comfortabele manier was om een proxy voor OpenAI te zetten - en tegelijkertijd de manier om deze instantie de opgeslagen sleutel, als 'autorisatie' van dat verzoek, naar een adres van iemand anders te laten dragen. Wie een bericht naar deze instantie kan sturen, zou dat kunnen doen. Een proxy hoort nu thuis in de configuratie, waar hij één keer wordt ingevoerd door degene die de adapter mag configureren. De redacteur heeft nooit een adres gestuurd, dus er verandert niets; de testknoppen van het instellingenvenster blijven proberen wat er in het formulier staat, met één limiet: een adres buiten het formulier telt alleen mee met een sleutel uit het formulier - de eigen sleutel tot het eigen eindpunt verraadt niets. In de modus voor het opslaan van inloggegevens wordt het opgeslagen adres gebruikt, dus er moet een eigen eindpunt worden opgeslagen voordat het daar kan worden getest.\nAlleen een item dat is opgeslagen als AI-inloggegevens, wordt gelezen uit de centrale opslag voor inloggegevens. De winkel bevat de geheimen van het hele systeem - een wachtwoord voor de database, de login van een camera - en een verzoek om „de sleutel van deze provider” zou elk van hen kunnen noemen\nHet `execute` bericht - dat hier een script uitvoert, met de hele IOBroker API erachter - checkt wie erom heeft gevraagd. In een bericht werd nooit gezegd namens wie het kwam, dus er was niets om te controleren, en iedereen die een bericht naar dit exemplaar zou sturen, kon code laten uitvoeren. Als de js-controller de gebruiker een naam geeft (7.2.5 en nieuwer, waardoor de gebruiker van een socketverbinding in het bericht wordt geplaatst), heeft die gebruiker het recht nodig heeft dat een commando op de host nodig heeft. Waar er geen naam wordt genoemd - een oudere controller, een script, een adapter - verandert er niets\nDe vraag vóór een foutopsporingssessie („Het script wordt gestopt en moet na de foutopsporing handmatig worden geactiveerd”) startte de foutopsporing, zelfs toen deze werd beantwoord met „Annuleren” (#2382)\nAls u een foutopsporingssessie stopt, kan het foutopsporingsproces worden beëindigd met „uncaught exception: write EPIPE”: het inspectieproces werd meteen afgesloten, hoewel het proces dat wordt gedebugd het hele logboek door de leidingen schrijft en nog steeds werd afgesloten. De inspecteur stopt nu eerst dat proces en wacht tot het echt weg is. Een kapotte pipe kan een script met foutopsporing niet meer beëindigen, en het opnieuw instellen van de verbinding met het foutopsporingsproces wordt niet gerapporteerd als een interne fout van de inspecteur (#2382)\nDe AI-chat bleef leeg wanneer een verzoek langer dan 30 seconden duurde: het antwoord wordt nu als een instantiebericht verzonden in plaats van te wachten tot het contact wordt teruggebeld\nEen AI-antwoord zonder inhoud zegt nu waarom (stop reden, token telt) in plaats van een lege chatballon achter te laten, en elk mislukt verzoek wordt geregistreerd\nEen antwoord dat bij de uitvoerlimiet wordt onderbroken, wordt als onvolledig gemarkeerd.\nDe scripts in de `@` lijst van de AI-chat gesorteerd op hun pad\nDe AI-chat kan worden gemaximaliseerd naar het hele redactiegebied (#2389)\nDe AI-chat toont een spinner voor het hele verzoek, niet alleen tot de eerste oproep tot de tool\nEen geaccepteerde AI-suggestie heeft de zichtbare editor niet bereikt\nProbleem opgelost dat de splitters terugsprongen naar hun vorige breedte terwijl ze werden gesleept\nBlockly: een parameter van een „JavaScript-functie” opgelost met de standaardnaam, waardoor het script niet kon worden opgeslagen\nScriptgeschiedenis toegevoegd: opgeslagen versies kunnen worden weergegeven, vergeleken en hersteld in de editor. „Opgeslagen versies per script” (standaard 30, 0 schakelt dit uit)\nEen tabblad „Scriptgeschiedenis” toegevoegd met de gebruikte opslag per script en knoppen om enkele, verweesde of alle geschiedenissen te verwijderen\nDe tabel met inloggegevens is verplaatst naar een eigen tabblad\nSpiegel: in een gewijzigd bestand worden niet langer de `enabled` en `engine` van het script gereset (#2396)",
|
|
49
|
+
"fr": "Le point final d'une demande d'IA provient de la configuration et non plus de la demande. Une adresse dans le message l'emportait sur celle enregistrée, ce qui était le moyen le plus simple de placer un proxy devant OpenAI, et en même temps de faire en sorte que cette instance transmette la clé stockée, en tant qu' « autorisation » de cette demande, à une adresse choisie par quelqu'un d'autre. Celui qui enverra un message à cette instance peut le faire. Un proxy a sa place maintenant, où il est saisi une seule fois par le configurateur de l'adaptateur. L'éditeur n'a jamais envoyé d'adresse, donc rien ne change ; les boutons Test de la boîte de dialogue des paramètres permettent d'essayer le contenu du formulaire, avec une limite : une adresse ne compte qu'avec une clé de formulaire. La clé de connexion de chacun à son propre point de terminaison ne donne rien. En mode Credential-Store, l'adresse enregistrée est utilisée, donc votre propre terminal doit être enregistré avant d'y être testé\nSeule une entrée enregistrée sous forme d'IA est lue dans la banque d'informations centrale. La boutique détient les secrets du système (mot de passe de base de données, identifiant d'une caméra) et une demande de « clé de ce fournisseur » pourrait nommer n'importe lequel\nLe message « Execute », qui lance un script ici, avec l'API complète d'IObroker, vérifie qui l'a demandé. Aucun message ne disait de qui il provenait, il n'y avait donc rien à vérifier, et tous ceux qui en envoyaient un à cette instance pouvaient exécuter du code. Lorsque le contrôleur JS donne un nom à l'utilisateur (version 7.2.5 et versions ultérieures, qui met l'utilisateur d'une connexion socket dans le message), il doit saisir une commande sur l'hôte. Là où il n'y en a pas, une ancienne manette, un script, un adaptateur, rien ne change\nLa question posée avant une session de débogage (« Le script sera arrêté et doit être activé manuellement après le débogage ») lançait le débogage même avec la réponse « Annuler » (#2382)\nL'arrêt d'une session de débogage pouvait mettre fin au processus avec « exception non détectée : écrivez EPIPE » : le processus d'inspection s'arrête immédiatement, alors que le processus écrit tout son journal et était toujours en train de s'arrêter. L'inspecteur arrête d'abord ce processus et attend qu'il soit vraiment terminé. Un tuyau cassé ne peut plus arrêter un script, et la réinitialisation de la connexion au processus n'est pas signalée comme une erreur interne de l'inspecteur (#2382)\nLe chat IA restait vide lorsqu'une demande durait plus de 30 secondes : la réponse est envoyée sous forme de message d'instance au lieu d'attendre le rappel\nUne réponse IA sans contenu explique pourquoi (raison de l'arrêt, compte) au lieu de laisser une bulle de discussion vide, et chaque échec est enregistré\nUne réponse coupée à la limite de sortie est marquée comme incomplète\nA trié les scripts de la liste « @ » du chat IA par chemin\nLe chat IA peut être étendu à l'ensemble de l'éditeur (#2389)\nLe chat IA affiche une liste complète de la requête, pas seulement avant le premier outil\nCorrection d'une suggestion d'IA acceptée qui n'atteignait pas l'éditeur\nCorrection des séparateurs qui revenaient à leur largeur d'origine\nBlockly : le nom par défaut d'une « fonction JavaScript » a été corrigé, rendant le script impossible à enregistrer\nAjout d'un historique des scripts : l'éditeur peut lister, comparer et restaurer les versions. « Versions enregistrées par script » (30 par défaut, 0 désactive)\nAjout d'un onglet « Historique des scripts » avec des boutons pour supprimer un historique, orphelin ou complet\nA déplacé le tableau des codes vers son propre onglet\nMiroir : un fichier modifié ne réinitialise plus « activé » et « moteur » du script (#2396)",
|
|
50
|
+
"it": "L'endpoint di una richiesta AI deriva dalla configurazione e non più dalla richiesta. Un indirizzo nel messaggio prevaleva su quello memorizzato, che era il modo più comodo per mettere un proxy davanti a OpenAI e per far sì che questa istanza portasse la chiave memorizzata, come «Autorizzazione» della richiesta, a un indirizzo scelto da qualcun altro. Chiunque invii un messaggio a questo caso può farlo. Il proxy fa parte della configurazione ora, e chi configura l'adattatore lo inserisce una volta. L'editor non ha mai inviato un indirizzo, quindi non cambia nulla; i pulsanti Test delle impostazioni continuano a provare ciò che è nel modulo, con un limite: un indirizzo fuori dal modulo conta solo insieme a una chiave. In modalità credenziali si usa l'indirizzo salvato, quindi è necessario salvare un endpoint prima di testarlo\nSolo una voce archiviata come credenziale AI viene letta dall'archivio centrale. Il negozio contiene i segreti del sistema: password del database, login di una telecamera, e richiedendo «la chiave di questo provider»\nIl messaggio `execute`, che esegue uno script con l'intera API IOBroker, verifica chi lo ha richiesto. Un messaggio non diceva da chi provenisse, quindi non c'era nulla da controllare e chiunque ne inviasse uno poteva far eseguire il codice. Se il js-controller nomina l'utente (7.2.5 e successivi, inserendo nel messaggio l'utente di una connessione socket), a quell'utente serve il diritto di comando sull'host. Se non ne nomina uno, un vecchio controller, uno script, non cambia nulla\nLa domanda prima di una sessione di debug («Lo script verrà interrotto e deve essere attivato manualmente dopo il debug») anche se ha risposto con «Annulla» (#2382)\nL'interruzione di una sessione di debug potrebbe terminare con «uncatch exception: write EPIPE»: il processo di ispezione è terminato subito, anche se il processo di debug scrive l'intero log nelle pipe e si sta ancora chiudendo. L'ispettore ora interrompe prima il processo e aspetta che finisca davvero, una pipe rotta non può più terminare uno script di debug e il ripristino della connessione non viene segnalato come errore interno (#2382)\nLa chat AI è rimasta vuota quando una richiesta richiedeva più di 30 secondi: ora la risposta viene inviata come istanza invece di\nUna risposta AI senza contenuto ora spiega perché (stop reason, token counts) invece di lasciare una chat vuota e ogni richiesta fallita\nUna risposta al limite di uscita è incompleta\nHa ordinato gli script della chat AI `@` in base al percorso\nLa chat AI può essere estesa a tutto l'editor (#2389)\nLa chat AI mostra l'intera richiesta, non solo fino al primo tool\nRisolto un problema AI accettato che non arrivava all'editor\nRisolto il problema con gli splitter che tornavano alla larghezza precedente\nBlockly: corretto un parametro di «funzione JavaScript» che rendeva lo script non salvabile\nCronologia script aggiunta: le versioni salvate sono confrontate e ripristinate «Versioni salvate per script» (30 di default, 0 lo spegne)\nAggiunta una scheda «Cronologia script» con spazio per script e pulsanti per eliminare singole o orfane\nHa spostato la tabella credenziali\nMirror: un file modificato non resetta più «enabled» e «engine» (#2396)",
|
|
51
|
+
"es": "El punto final de una solicitud de IA sale de la configuración y ya no de la solicitud. Una dirección en el mensaje solía ganarse a la almacenada, que era la forma más cómoda de poner un proxy delante de OpenAI y, al mismo tiempo, hacer que esta instancia llevara la clave almacenada, como «Autorización» de esa solicitud, a la dirección que eligiera otra persona. Quienquiera que envíe un mensaje a esta instancia puede hacerlo. El proxy pertenece a la configuración ahora, donde lo introduce una vez quien configure el adaptador. El editor nunca envió una dirección, así que no cambia nada; los botones de prueba del cuadro de diálogo de ajustes siguen intentando lo que hay en el formulario, con un límite: una dirección fuera del formulario solo cuenta junto con una clave fuera del formulario; la propia clave del punto final no revela nada. En el modo almacén de credenciales se usa la dirección guardada, por lo que hay que guardar un punto final propio antes de poder probarlo allí\nEn la tienda central de credenciales solo se lee una entrada guardada como credencial de IA. La tienda guarda los secretos de todo el sistema (la contraseña de una base de datos, el inicio de sesión de una cámara) y solicitar «la clave de este proveedor» podría nombrar a cualquiera de ellos\nEl mensaje «ejecutar», que ejecuta un guion aquí, con toda la API de IOBroker detrás, comprueba quién lo pidió. Un mensaje nunca decía en nombre de quién venía, así que no había nada que comprobar y cualquiera que enviara uno a esta instancia podría ejecutar código. Cuando el controlador js nombra al usuario (7.2.5 y posterior, que pone al usuario de una conexión de socket en el mensaje), ese usuario necesita el derecho que necesita un comando del host. Cuando no nombra uno (un mando, un guion, un adaptador antiguo), nada cambia\nLa pregunta antes de una sesión de depuración («El guion se detendrá y se activará manualmente tras la depuración») inició la depuración incluso cuando se respondió con «Cancelar» (#2382)\nDetener una sesión de depuración podría terminar el proceso con una «excepción no detectada: escriba EPIPE»: el proceso del inspector salió de una vez, aunque el proceso que depura escribe todo su registro y seguía cerrándose. El inspector ahora detiene primero el proceso y espera a que termine, una tubería rota ya no puede terminar un guion depurado y el restablecimiento de la conexión al proceso depurado no se informa como error interno del inspector (#2382)\nEl chat de IA permaneció vacío cuando una solicitud tardó más de 30 segundos: la respuesta se envía como mensaje de instancia en lugar de esperar a la llamada del socket\nUna respuesta de IA sin contenido ahora dice por qué (detener motivo, cuenta fichas) en lugar de dejar una burbuja de chat vacía, y cada solicitud fallida se registra\nUna respuesta cortada en el límite de salida está incompleta\nOrdenó los guiones de la lista `@ del chat de IA por ruta\nEl chat de IA se puede maximizar en toda el área de edición (#2389)\nEl chat de IA muestra una ruleta para toda la solicitud, no solo hasta la primera llamada\nSe corrigió una sugerencia de IA aceptada que no llegaba al editor visible\nSe ha corregido que los divisores volvieran a su ancho anterior al arrastrarlos\nBlockly: se ha corregido un parámetro de una «función de JavaScript» con su nombre por defecto que no se podía guardar\nAñadió un historial de guiones: las versiones guardadas se muestran, comparan y restauran en el editor. «Versiones guardadas por guion» (30 por defecto, 0 lo desactiva)\nSe ha añadido una pestaña de «Historial de guiones» con el almacenamiento de cada guion y botones para borrar un solo historial, huérfano o todo\nMovió la tabla de credenciales a su pestaña\nEspejo: un archivo cambiado ya no restablece «activado» y «motor» del guion (#2396)",
|
|
52
|
+
"pl": "Punkt końcowy żądania AI wychodzi z konfiguracji i nie jest już poza żądaniem. Adres w wiadomości używany do zdobycia zapisanego adresu, co było wygodnym sposobem umieszczenia proxy przed OpenAI - a jednocześnie sposobem, aby ta instancja przenosiła przechowywany klucz, jako „Autoryzacja” tego żądania, na adres wybrany przez kogoś innego. Ktokolwiek może wysłać wiadomość do tej instancji, może to zrobić. Serwer proxy należy teraz do konfiguracji, gdzie jest wprowadzany raz przez każdego, kto może skonfigurować adapter. Edytor nigdy nie wysłał adresu, więc nic się nie zmienia; przyciski Test w oknie dialogowym ustawień wciąż próbują tego, co znajduje się w formularzu, z jednym limitem: adres poza formularzem liczy się tylko razem z kluczem z formularza - własny klucz do własnego punktu końcowego nic nie daje. W trybie przechowywania poświadczeń używany jest zapisany adres, więc własny punkt końcowy musi zostać zapisany, zanim będzie można go tam przetestować\nTylko wpis, który został zapisany jako dane uwierzytelniające AI, jest odczytywany z centralnego magazynu poświadczeń. Sklep przechowuje tajemnice całego systemu - hasło do bazy danych, login kamery - a prośba o „klucz tego dostawcy” może wymienić dowolny z nich\nKomunikat `execute` - który uruchamia tutaj skrypt, za którym znajduje się cały interfejs API ioBroker - sprawdza, kto o to poprosił. Wiadomość nigdy nie powiedziała, w czyim imieniu przyszła, więc nie było nic do sprawdzenia, a każdy, kto może wysłać ją do tej instancji, mógł wykonać kod. Tam, gdzie kontroler js nazywa użytkownika (7.2.5 i nowszy, który umieszcza użytkownika połączenia gniazda w wiadomości), ten użytkownik potrzebuje prawa, którego potrzebuje polecenie na hoście. Gdzie nie nazywa jednego - starszy kontroler, skrypt, adapter - nic się nie zmienia\nPytanie przed sesją debugowania („Skrypt zostanie zatrzymany i musi zostać aktywowany ręcznie po debugowaniu”) rozpoczęło debugowanie nawet wtedy, gdy odpowiedziano na nie „Anuluj” (#2382)\nZatrzymanie sesji debugowania może zakończyć proces debugowania „niewychwytywany wyjątek: napisz EPIPE”: proces inspektora zakończył się natychmiast, chociaż proces, który debuguje, zapisuje cały dziennik przez swoje rury i nadal się zamykał. Inspektor najpierw zatrzymuje ten proces i czeka, aż naprawdę zniknie, zepsuta rura nie może już zakończyć debugowanego skryptu, a zresetowanie połączenia z debugowanym procesem nie jest zgłaszane jako wewnętrzny błąd inspektora (#2382)\nCzat AI pozostał pusty, gdy żądanie trwało dłużej niż 30 sekund: odpowiedź jest teraz przesyłana jako wiadomość instancji zamiast czekać na wywołanie zwrotne gniazda\nOdpowiedź AI bez treści mówi teraz, dlaczego (powód zatrzymania, liczenie tokenów) zamiast pozostawiać pustą bańkę czatu, a każde nieudane żądanie jest rejestrowane\nOdpowiedź odcięta na granicy wyjściowej jest oznaczona jako niekompletna\nPosortowane skrypty na liście `@` czatu AI według ich ścieżki\nCzat AI można zmaksymalizować do całego obszaru edytora (#2389)\nCzat AI pokazuje spinner dla całego żądania, nie tylko do pierwszego wywołania narzędzia\nNaprawiono zaakceptowaną sugestię AI, która nie dotarła do widocznego edytora\nNaprawiono rozgałęźniki przeskakujące z powrotem do poprzedniej szerokości podczas przeciągania\nBlockly: naprawiono parametr „funkcji JavaScript” z jej domyślną nazwą, co uniemożliwia zapisanie skryptu\nDodano historię skryptów: zapisane wersje można wyświetlać, porównywać i przywrócić w edytorze. „Zapisane wersje na skrypt” (domyślnie 30, 0 wyłącza go)\nDodano zakładkę „Historia skryptów” z używaną pamięcią na skrypt i przyciskami do usuwania pojedynczych, osieroconych lub wszystkich historii\nPrzeniesiono tabelę poświadczeń na własną kartę\nMirror: zmieniony plik nie resetuje już „włączonego” i „silnika” skryptu (#2396)",
|
|
53
|
+
"uk": "Кінцева точка запиту AI виходить із конфігурації, а більше не із запиту. Адреса в повідомленні використовувалася для перемоги над збереженим, що було зручним способом поставити проксі перед OpenAI - і в той же час спосіб, щоб цей екземпляр переносив збережений ключ, як «Авторизація» цього запиту, на адресу, яку хтось вибрав. Той, хто може надіслати повідомлення цій інстанції, може це зробити. Проксі-сервер зараз належить до конфігурації, де його вводить один раз той, хто може налаштувати адаптер. Редактор ніколи не надсилав адресу, тому для неї нічого не змінюється; кнопки «Тест» діалогового вікна налаштувань продовжують пробувати те, що стоїть у формі, з одним обмеженням: адреса поза формою враховується лише разом із ключем поза формою - власний ключ до власної кінцевої точки нічого не дає. У режимі сховища облікових даних використовується збережена адреса, тому перед тим, як її можна буде перевірити там, потрібно зберегти власну кінцеву точку\nЛише запис, який був збережений як обліковий запис AI, читається з центрального сховища облікових даних. У магазині зберігаються секрети всієї системи - пароль бази даних, логін камери - і запит на «ключ цього провайдера» міг назвати будь-який з них\nПовідомлення `execute` - яке запускає тут скрипт, з усім API IObroker за ним - перевіряє, хто його запитав. У повідомленні ніколи не було сказано, від чиго імені воно прийшло, тому перевіряти нічого, і кожен, хто може надіслати його на цей екземпляр, міг виконати код. Якщо js-контролер називає користувача (7.2.5 і новіших версій, які поміщають користувача підключення до сокета в повідомлення), цьому користувачеві потрібно право, яке потрібно команді на хості. Де не називає одного - старий контролер, скрипт, адаптер - нічого не змінюється\nПитання перед сеансом налагодження («Скрипт буде зупинений і повинен бути активований вручну після налагодження») запустило налагодження навіть тоді, коли на нього відповіли «Скасувати» (#2382)\nЗупинення сеансу налагодження може завершити налагоджений процес із «незловленим винятком: запишіть EPIPE»: процес інспектора вийшов одразу, хоча процес, який він налагоджує, записує весь свій журнал через свої труби і все ще вимикався. Тепер інспектор спочатку зупиняє цей процес і чекає, поки він дійсно зникне, зламана труба більше не може закінчити налагоджений скрипт, а скидання з'єднання з налагодженим процесом не повідомляється як внутрішня помилка інспектора (#2382)\nЧат AI залишався порожнім, коли запит тривав більше 30 секунд: відповідь тепер передається як повідомлення про екземпляр замість того, щоб чекати зворотного виклику сокета\nВідповідь AI без вмісту тепер говорить чому (причина зупинки, кількість токенів) замість того, щоб залишати порожню бульбашку чату, і кожен невдалий запит реєструється\nВідповідь, відрізана на вихідній межі, позначається як неповна\nСортування скриптів у списку `@` чату AI за їх шляхом\nЧат AI може бути максимально розширений для всієї області редактора (#2389)\nЧат AI показує спіннер для всього запиту, не тільки до першого виклику інструменту\nВиправлено прийняту пропозицію AI, яка не потрапляє до видимого редактора\nВиправлено, коли спліттери повертаються до попередньої ширини під час перетягування\nBlockly: виправлено параметр «функції JavaScript» з її назвою за замовчуванням, що робить сценарій непридатним для збереження\nДодана історія скриптів: збережені версії можна перерахувати, порівнювати та відновлювати в редакторі. «Збережені версії для скрипту» (30 за замовчуванням, 0 вимикає його)\nДодана вкладка «Історія сценаріїв» з використовуваним сховищем для скрипта та кнопками для видалення одиничних, осиротілих або всіх історій\nПереміщено таблицю облікових даних на власну вкладку\nДзеркало: змінений файл більше не скидає `enabled` і `engine` скрипта (#2396)",
|
|
54
|
+
"zh-cn": "AI 请求的端点来自配置,不再来自请求。消息中的一个地址过去用来赢得存储的地址,这是在 OpenAI 面前放置代理的便捷方式,同时也是让该实例将存储的密钥(作为该请求的 “授权”)携带到他人选择的地址的方法。任何可以向该实例发送消息的人都可以这样做。代理现在属于配置中,任何可以配置适配器的人都只能输入一次代理。编辑器从未发送过地址,因此没有任何变化;设置对话框的测试按钮一直在尝试表单中的内容,但有一个限制:表单中的地址只能与表单中的密钥一起计算——一个人自己访问自己端点的密钥不会泄露任何东西。在凭证存储模式下,使用保存的地址,因此必须先保存自己的端点,然后才能在那里进行测试\n只有作为 AI 凭据存储的条目才能从中央凭证存储中读取。商店保存着整个系统的秘密——数据库密码、摄像机的登录名——而请求 “这个提供商的密钥” 可以说出其中任何一个的名字\n“执行” 消息——它在这里运行一个脚本,背后是整个 IOBroker API ——检查是谁要求的。一条消息从来没有说过是代表谁来的,所以没有什么可检查的,每个可能向这个实例发送一条消息的人都可以执行代码。其中 js-controller 命名用户(7.2.5 及更高版本,它将套接字连接的用户放入消息中),则该用户需要主机上命令所需的权限。它没有命名的地方 —— 较旧的控制器、脚本、适配器 —— 没有任何变化\n调试会话之前的问题(“脚本将停止,调试后必须手动激活”)启动了调试,即使回答 “取消” (#2382)\n停止调试会话可能会以 “未捕获的异常:写入 EPIPE” 结束调试进程:检查器进程立即退出,尽管它调试的进程通过管道写入了全部日志,并且仍在关闭。检查器现在会先停止该进程,然后等到它真正消失,管道损坏无法再结束已调试的脚本,并且重置与调试进程的连接不会被报告为检查器的内部错误 (#2382)\n当请求花费超过 30 秒时,AI 聊天将保持空白:答案现在作为实例消息推送,而不是等待套接字回调\n没有内容的 AI 答案现在会显示原因(停止原因、令牌数),而不是留下空的聊天气泡,并且每个失败的请求都会被记录下来\n输出限制处截止的答案被标记为不完整\n按路径对 AI 聊天的 `@` 列表中的脚本进行排序\nAI 聊天可以最大化到整个编辑器区域 (#2389)\nAI 聊天会显示整个请求的微调器,不仅仅是第一次工具调用\n修复了接受的 AI 建议无法到达可见编辑器的问题\n修复了分离器在被拖动时会跳回之前的宽度的问题\nBlockly:修复了使用默认名称的 “JavaScript 函数” 的参数使脚本无法保存的问题\n添加了脚本历史记录:可以在编辑器中列出、比较和恢复保存的版本。“每个脚本保存的版本”(默认为 30,0 将其关闭)\n添加了 “脚本历史记录” 选项卡,其中包含每个脚本使用的存储空间以及用于删除单个、孤立或所有历史记录的按钮\n已将凭据表移至其自己的选项卡\n镜像:更改后的文件不再重置脚本的 “已启用” 和 “引擎” (#2396)"
|
|
55
|
+
},
|
|
43
56
|
"10.3.0": {
|
|
44
57
|
"en": "The code editor (Monaco), Blockly and the Rules blocks are loaded only when a script of that kind is opened, so the editor starts faster\nAdded function block diagrams (FBD, in the style of CFC): timers, counters, flip-flops, edges, comparison, arithmetic, conversions, control, calendar (cron, sun events), log and messages, and a block with own JavaScript - wired to ioBroker states. See [the description](docs/en/fbd.md)",
|
|
45
58
|
"de": "Die Blöcke Code-Editor (Monaco), Blockly und Rules werden nur geladen, wenn ein Skript geöffnet wird.\nFunktionsblockdiagramme (FBD, im CFC-Stil) hinzugefügt: Timer, Zähler, Flipflops, Kanten, Vergleich, Arithmetik, Umrechnungen, Kalender (Cron, Sun), Log und Nachrichten und ein Block mit eigenem JavaScript — mit ioBroker-Status. Siehe [Beschreibung] (docs/en/fbd.md)",
|
|
@@ -117,19 +130,6 @@
|
|
|
117
130
|
"pl": "Zasady: wybór stanu stałego",
|
|
118
131
|
"uk": "Правила: вибір штату фіксований",
|
|
119
132
|
"zh-cn": "规则:选州固定"
|
|
120
|
-
},
|
|
121
|
-
"10.2.0": {
|
|
122
|
-
"en": "Rules: an empty \"and\" band folds down to its heading. A rule without conditions runs its actions on every trigger, but that band was still the tallest thing in the rule - a drop area with a 64px floor, the \"just check\" selector and an \"or\" row per group, 292px for nothing. It is 41px now and says \"without condition\", clicking the heading opens it again, dragging a condition over it opens it by itself, and a band that has conditions in it never folds\nRules: the block palette takes half the room it did. An entry carried 24px of padding around a 30px icon, which left 66px of sidebar for one line of text - so four blocks filled the whole height and everything else was behind a scrollbar. Entries are 31px apart now, the icon-only tabs above them no longer reserve the height of a label they do not have, and the sidebar is 168px instead of 200px wide. A name too long for that gets the full text as its tooltip. The button that folds the palette away also sits on the palette's line now instead of one pixel to the left of it, where it hung over the edge of the window once the palette was folded away\nRules: picking the state of a trigger took the editor down with \"n.replace is not a function\" when a condition on a string state had no value entered yet. Choosing a state compiles the whole rule again, and the empty value arrived at the comparison as the boolean `false`. A condition without a value now compares against an empty text, and a number entered for a state that is a string is used as its text\nThe script editor now tells the adapter every 10 seconds that it is open, and the adapter keeps the type definitions and the compiler hot while that is the case, so saving a script does not wait for them to be built again. 30 seconds after the last sign of life the GUI counts as gone and everything is given back - about 100 MB. A tab in the background does not count as open, so a forgotten browser tab cannot keep the memory alive for days (#2373)\nThe type definitions of Node.js, ioBroker and the configured libraries were read at every start, whether anything wanted them or not. Only two things do - compiling a TypeScript script and the built-in editor - and they add about 90 MB to the compiler, so they are now read when one of those actually asks. An instance that runs plain JavaScript and is edited elsewhere (mirror directory, external editor) never reads them; the declarations of global JavaScripts are generated without them and come out the same. They can also be switched off for good (\"Load type definitions\", TypeScript tab) - the editor then loses its autocompletion and TypeScript scripts no longer compile, which the adapter warns about in the log (#2373)\nEvery instance kept two TypeScript language services alive whether it needed them or not, and each one held on to about 95 MB once it had compiled anything. They are now built on the first compilation only, and the declarations of global JavaScripts are stored on the script object the same way compiled TypeScript sources already were - so a restart no longer regenerates them. What a language service does end up building is released again a minute after the last compilation and rebuilt on demand. On a test system this took an instance from 241 MB to 127 MB heap (352 MB to 233 MB RSS) (#2373)\nThe helpers that the script editor draws on its own - the \"Explain / Refactor / Test\" row above every function, the tooltips for object IDs and CRON expressions, and the inline code suggestions - can be switched off. The instance setting \"Show AI helpers in the script editor\" (AI settings) does it; it is on by default, so nothing changes for anyone who is happy with them. `Alt+I` still shows the value of the object ID under the cursor when they are off\nThe reasoning of an OpenAI-compatible endpoint was switched off unconditionally: `reasoning_effort: \"none\"` went out with every request as soon as a custom base URL was configured. That is right for a small local model and wrong for everything else - behind a proxy it turns off the reasoning of the very model one is paying for, or is rejected. It is a setting now (\"Reasoning effort\"), and the default leaves the parameter out and lets the endpoint decide\nThe AI editor told the adapter how long it was willing to wait, and the adapter never read it: a stuck inline completion held its slot for the full ten minutes instead of the fifteen seconds it asked for\nThe inline completion took the model chosen in the AI chat but picked the provider itself, so a model of one provider could be requested with the credentials and at the endpoint of another. Model and provider are now remembered and used together\nWhen two providers offer a model of the same name - a proxy and the vendor behind it, for instance - which of them served it was decided by whichever answered first, and could change from one reload to the next. The provider configured first wins now, so the direct route is preferred over a proxy",
|
|
123
|
-
"de": "Regeln: Ein leeres „Und“ -Band klappt nach unten. Eine Regel ohne Bedingungen führt ihre Aktionen bei jedem Auslöser aus, aber das Band war immer noch am höchsten — ein Drop-Bereich mit 64 Pixeln, „Just check“ -Selektor und „oder“ -Reihe pro Gruppe, 292 px umsonst. Es ist jetzt 41 Pixel groß und sagt „ohne Bedingung“. Ein Klick auf die Überschrift öffnet sie erneut, und ein Band mit Bedingungen klappt nie.\nRegeln: Die Blockpalette nimmt halb so viel Platz ein. Ein Eintrag war 24 px rund um ein 30-Pix-Symbol, sodass 66 px Seitenleiste für eine Textzeile übrig waren — vier Blöcke füllten die ganze Höhe und alles andere war hinter einer Scrollleiste. Die Einträge sind jetzt 31 Pixel auseinander, die Tabs über ihnen haben keine Labelhöhe mehr und die Seitenleiste ist 168 Pixel statt 200 Pixel breit. Ein zu langer Name hat den Volltext als Tooltip. Die Schaltfläche zum Einklappen der Palette befindet sich jetzt auch auf der Linie der Palette und nicht ein Pixel links davon, wo sie nach dem Zusammenklappen über dem Fensterrand hing\nRegeln: Wenn der Status eines Triggers noch kein Wert eingegeben wurde, sagte der Editor „n.replace ist keine Funktion“. Wenn Sie ein Bundesland wählen, wird die Regel erneut kompiliert, und der leere Wert ergab den booleschen Wert Eine Bedingung ohne Wert wird nun mit leerem Text verglichen, und als Text wird eine Zahl für ein Bundesland verwendet\nDer Skripteditor teilt dem Adapter nun alle 10 Sekunden mit, dass er geöffnet ist, und hält dabei die Typdefinitionen und den Compiler heiß. Das Speichern eines Skripts wartet nicht, bis es neu erstellt wird. 30 Sekunden nach dem letzten Lebenszeichen gilt die GUI als weg und alles wird zurückgegeben — etwa 100 MB. Ein Tab im Hintergrund gilt nicht als geöffnet, ein vergessener Browser-Tab hält ihn tagelang fest (#2373)\nDie Typdefinitionen von Node.js, ioBroker und die konfigurierten Bibliotheken wurden bei jedem Start gelesen. Nur zwei Dinge tun das — ein TypeScript-Skript und der eingebaute Editor — und sie erhöhen den Compiler um 90 MB, sodass sie gelesen werden, wenn einer fragt. Eine Instanz, die reines JavaScript ausführt und woanders bearbeitet wird (Spiegelverzeichnis, externer Editor), liest sie nie. Die Deklarationen globaler JavaScripts werden ohne sie generiert. Sie sind auch endgültig abschaltbar („Load Type Definitions“, Tab TypeScript) — dann verliert der Editor seine Autokomplettierung und TypeScript-Skripte kompilieren nicht mehr, wovor der Adapter warnt (#2373)\nJede Instanz hielt zwei TypeScript-Sprachdienste am Leben, ob nötig oder nicht, und jede hielt etwa 95 MB, nachdem sie etwas kompiliert hatte. Sie basieren jetzt nur auf der ersten Compilierung und globale JavaScript-Deklarationen werden im Skriptobjekt gespeichert, so dass sie bei einem Neustart nicht mehr neu generiert werden. Was ein Sprachdienst baut, wird eine Minute nach der letzten Compilation erneut veröffentlicht. Auf einem Testsystem waren es 241 MB auf 127 MB Heap (352 MB bis 233 MB RSS) (#2373)\nDie vom Skripteditor selbst erstellten Helfer — die Zeile „Explain/Refactor/Test“ über jeder Funktion, Tooltips für Objekt-IDs und CRON-Ausdrücke und Inline-Codevorschläge — können abgeschaltet werden. Die Instanzeinstellung „Zeige KI-Helfer im Skripteditor“ (AI-Einstellungen) tut das. Sie ist standardmäßig aktiviert, also ändert sich nichts. `Alt+I` zeigt auch bei ausgeschaltetem Cursor den Wert der Objekt-ID\nDie Logik eines OpenAI-fähigen Endpunkts wurde bedingungslos abgeschaltet: `reasoning_effort: „none\"` ging bei jeder Anfrage raus, sobald eine benutzerdefinierte Basis-URL konfiguriert war. Das stimmt für ein kleines Lokalmodell und falsch für alles andere. Hinter einem Proxy steht das Modell, für das man bezahlt, oder es wird abgelehnt. Es ist jetzt eine Einstellung („Argumentationsaufwand“), ohne Parameter und der Endpunkt entscheidet\nDer KI-Editor teilte dem Adapter mit, wie lange er bereit war zu warten, und der Adapter las ihn nie: Ein hängengebliebener Inline-Slot hielt die vollen zehn Minuten statt 15 Sekunden\nBeim Inline-Abschluss wurde das im KI-Chat gewählte Modell, aber der Anbieter selbst ausgewählt, sodass ein Modell mit den Zugangsdaten und am Ende eines anderen angefragt werden konnte. Modell und Anbieter werden nun gespeichert und genutzt\nWenn zwei Anbieter ein Modell mit dem gleichen Namen anbieten, z. B. einen Proxy und den Anbieter dahinter, entscheidet, wer zuerst antwortet, und kann von einem Reload zum nächsten wechseln. Der erste Anbieter gewinnt jetzt, der direkte Weg wird einem Proxy vorgezogen",
|
|
124
|
-
"ru": "Правила: пустая полоса «и» сворачивается к заголовку. Правило без условий срабатывает при каждом триггере, но эта полоса всё равно оставалась самой высокой в правиле — зона выпадения с полом размером 64 пикселя, селектор «просто галочка» и строка «или» на группу, 292 пикселя даром. Теперь оно составляет 41 пиксель и написано «без условий», при нажатии на заголовок оно снова открывается, при перетаскивании условия оно открывается само по себе, а полоса, в которой есть условия, никогда не сворачивается\nПравила: блочная палитра занимает вдвое меньше места, чем раньше. Значок размером 30 пикселей составлял 24 пикселя, в результате чего на одной строке текста оставалось 66 пикселей боковой панели. Таким образом, четыре блока заполнили всю высоту, а все остальное — за полосой прокрутки. Теперь расстояние между записями составляет 31 пиксель, а расположенные над ними вкладки, содержащие только значки, больше не сохраняют высоту метки, которой у них нет, а ширина боковой панели составляет 168 пикселей вместо 200 пикселей. При слишком длинном названии в виде всплывающей подсказки отображается полный текст. Кнопка, откидывающая палитру, теперь также находится на линии палитры, а не на одном пикселе слева от нее. Как только палитра была сложена, она висела над краем окна\nПравила: при выборе состояния триггера редактор выводил сообщение «n.replace is not a function», когда условие в строковом состоянии еще не было введено ни одного значения. При выборе состояния все правило снова компилируется, а пустое значение при сравнении выводится как логическое значение «false». Условие без значения теперь сравнивается с пустым текстом, а в качестве текста используется число, введенное для состояния, представляющего собой строку\nТеперь редактор сценариев сообщает адаптеру каждые 10 секунд о том, что он открыт, а определения типов и компилятор остаются в рабочем состоянии, поэтому сохранение скрипта не дожидается его повторной сборки. Через 30 секунд после появления последних признаков жизни графический интерфейс считается исчерпанным и все возвращено обратно — около 100 МБ. Вкладка в фоновом режиме не считается открытой, поэтому забытая вкладка браузера не сможет сохранить память в течение нескольких дней (#2373)\nОпределения типов Node.js, IOBroker и настроенных библиотек считывались при каждом запуске, независимо от того, хотели они того или нет. Только две вещи — компиляция сценария TypeScript и встроенного редактора — и они добавляют компилятору около 90 МБ, поэтому теперь они читаются, когда кто-то из них действительно запрашивает. Экземпляр, работающий под управлением обычного JavaScript и редактируемый в другом месте (зеркальный каталог, внешний редактор), никогда не читает их; объявления глобальных JavaScripts генерируются без них и получаются одинаковыми. Их также можно навсегда отключить («Загрузить определения типов», вкладка TypeScript) — в этом случае редактор теряет автозаполнение, а скрипты TypeScript перестают компилироваться, о чем адаптер предупреждает в журнале (#2373)\nВ каждом экземпляре две языковые службы TypeScript работали независимо от того, были ли они нужны или нет, и каждая из них после компиляции занимала около 95 МБ. Теперь они основаны только на первой компиляции, а объявления глобальных JavaScript хранятся в объекте сценария так же, как и скомпилированные исходники TypeScript, поэтому при перезапуске они больше не восстанавливаются. То, что в конечном итоге создает языковой сервис, снова публикуется через минуту после последней компиляции и перестраивается по запросу. В тестовой системе объем кучи в экземпляре составлял от 241 МБ до 127 МБ (с 352 МБ до 233 МБ в формате RSS) (#2373)\nПомощники, которые редактор сценариев использует самостоятельно — строку «Explain/Refactor/Test» над каждой функцией, всплывающие подсказки для идентификаторов объектов и выражений CRON, а также встроенные рекомендации по коду — можно отключить. Параметр экземпляра «Показать помощников искусственного интеллекта в редакторе сценариев» (настройки ИИ) работает; по умолчанию он включен, поэтому для всех, кому они нравятся, ничего не меняется. В выключенном режиме «Alt+I» по-прежнему отображается значение идентификатора объекта под курсором\nОбоснование наличия конечной точки, совместимой с OpenAI, было безоговорочно опровергнуто: `reasoning_effort: «none\"` отправлялось с каждым запросом, как только был настроен собственный базовый URL-адрес. Это верно для небольшой локальной модели и неправильно для всего остального: прокси-сервер отключает аргументы в пользу той самой модели, за которую вы платите, или отклоняется. Теперь это настройка («Усилия по обоснованию»), но по умолчанию этот параметр не используется, а решение остаётся за конечной точкой\nРедактор искусственного интеллекта сообщил адаптеру, сколько он готов ждать, но адаптер так и не прочитал его: из-за зависания в строке ввода слот удерживался целых десять минут, а не пятнадцать секунд, как того требовалось\nПри заполнении в интерактивном режиме использовалась модель, выбранная в чате с искусственным интеллектом, но выбирался сам поставщик, поэтому можно было запросить модель одного поставщика с учетными данными и на конечной точке другого. Теперь модель и провайдер запоминаются и используются вместе\nКогда два провайдера предлагают модель с одинаковым названием (например, прокси-сервер и поставщик, стоящий за ним), выбор того, кто из них обслужил, решал тот, кто ответил первым, и может меняться от одной перезагрузки к следующей. Теперь выигрывает тот провайдер, который настроил первым, поэтому предпочтение отдается прямому маршруту, а не прокси-серверу",
|
|
125
|
-
"pt": "Regras: uma faixa “e” vazia se dobra até o título. Uma regra sem condições executa suas ações em cada gatilho, mas essa faixa ainda era a mais alta: uma área de 64 px, o seletor “just check” e uma linha “ou” por grupo, 292 px à toa. Agora tem 41px e diz “sem condição”, clicar no título a abre novamente, arrastar uma condição sobre ela a abre sozinha, e uma faixa com condições nunca se dobra\nRegras: a paleta de blocos ocupa metade. Uma entrada tinha 24px de espaço em torno de um ícone de 30px, deixando 66px de barra lateral para uma linha de texto — então quatro blocos ocupavam toda a altura e rolavam. As entradas estão separadas por 31 px, as abas com ícones não têm mais a altura de um rótulo que não têm e a barra lateral tem 168 px em vez de 200 px. Um nome longo demais tem o texto completo como dica. O botão que dobra a paleta também fica na linha da paleta agora, em vez de um pixel à esquerda, onde ficava na borda da janela quando a paleta era dobrada.\nRegras: escolher o estado de um gatilho dizia “n.replace is not a function” quando uma condição em uma string ainda não tinha valor inserido. A escolha de um estado compila toda a regra e o valor vazio chegou à comparação como booleano `false`. Uma condição sem valor agora se compara a um texto vazio e um número inserido em uma string é usado como texto\nO editor de scripts agora informa ao adaptador a cada 10 segundos que ele está aberto, e o adaptador mantém as definições de tipo e o compilador ativos. Salvar um script não espera que ele seja reconstruído. 30 segundos após o último sinal de vida, a GUI é considerada perdida e tudo é devolvido - cerca de 100 MB. Uma aba no fundo não conta como aberta, então uma aba esquecida não mantém a memória viva por dias (#2373)\nAs definições de tipo de Node.js, IOBroker e das bibliotecas configuradas foram lidas sempre, querendo ou não. Apenas duas coisas — compilar um script TypeScript e um editor embutido — adicionam cerca de 90 MB ao compilador e agora são lidos quando alguém pede. Uma instância que executa JavaScript puro e é editada em outro lugar (diretório espelho, editor externo) nunca os lê; as declarações de JavaScripts globais são geradas sem elas e saem iguais. Eles também podem ser desativados para sempre (“Definições de tipo de carga”, guia TypeScript) - o editor perde o preenchimento automático e os scripts não são mais compilados, o que o adaptador avisa no log (#2373)\nCada instância mantinha dois serviços da linguagem TypeScript ativos, precisando ou não, e cada um tinha cerca de 95 MB após compilar algo. Agora, elas se baseiam apenas na primeira compilação e as declarações globais de JavaScript são armazenadas no objeto de script da mesma forma que as fontes compiladas do TypeScript. O que um serviço de linguagem cria é lançado um minuto após a última compilação e reconstruído sob demanda. Em um sistema de teste, isso levou de 241 MB a 127 MB de heap (352 MB a 233 MB RSS) (#2373)\nOs auxiliares que o editor de script usa sozinho — a linha “Explain/Refactor /Test” acima de cada função, as dicas para IDs de objetos e expressões CRON e as sugestões de código — podem ser desativados. A configuração de instância “Mostrar ajudantes de IA no editor de scripts” faz isso; ela está ativada por padrão, então nada muda para quem gosta deles. `Alt+I` ainda mostra o valor do ID do objeto sob o cursor quando desligado\nO raciocínio de um endpoint compatível com OpenAI era incondicional: `reasoning_effort: “none\"` saía com cada solicitação assim que um URL base customizado era configurado. Isso é certo para um modelo local pequeno e errado para todo o resto: por trás de um proxy, ele desativa o raciocínio do modelo pelo qual se paga ou é rejeitado. Agora é uma configuração (“Reasoning effort”), e o padrão exclui o parâmetro e deixa o endpoint decidir\nO editor de IA disse ao adaptador quanto tempo ele estava disposto a esperar e ele nunca o leu: um preenchimento em linha travado manteve o slot por dez minutos, em vez dos quinze segundos necessários\nO preenchimento em linha usou o modelo escolhido no chat de IA, mas escolheu o provedor em si, para solicitar o modelo de um provedor com as credenciais e no terminal de outro. Modelo e provedor agora são lembrados e usados juntos\nQuando dois provedores oferecem um modelo com o mesmo nome — um proxy e o fornecedor por trás dele — qual deles atendia, quem respondia primeiro e pode mudar de uma recarga para outra. O primeiro provedor vence agora, então a rota direta é preferida a um proxy",
|
|
126
|
-
"nl": "Regels: een lege „en” band kan naar beneden worden gevouwen tot aan de kop. Een regel zonder voorwaarden voert op elke trigger zijn acties uit, maar die band was nog steeds het grootste punt in de regel: een dropzone met een vloer van 64 px, de selector „even checken” en een rij „of” per groep, 292 px voor niets. Het is nu 41 px en er staat „zonder voorwaarde”. Als u op de kop klikt, wordt de toestand weer geopend, als u een voorwaarde eroverheen sleept, wordt deze vanzelf geopend, en een band met voorwaarden wordt nooit gevouwen\nRegels: het blokpalet neemt de helft van de ruimte in beslag. Een item bevatte 24 px opvulling rond een pictogram van 30 px, waardoor er 66 px aan zijbalk overbleef voor één regel tekst - dus vier blokken vulden de hele hoogte en al het andere zat achter een schuifbalk. De items staan nu 31 pixels uit elkaar, op de tabbladen met alleen pictogrammen erboven is niet langer de hoogte gereserveerd van een label dat ze niet hebben, en de zijbalk is 168 px in plaats van 200 px breed. Een naam die te lang is daarvoor, krijgt de volledige tekst als tooltip. De knop waarmee het palet wordt weggevouwen, bevindt zich nu ook op de lijn van het palet, in plaats van één pixel links ervan, waar hij boven de rand van het venster hing toen het palet was weggevouwen\nRegels: door de status van een trigger te kiezen, werd de editor uitgeschakeld met „n.replace is geen functie” toen er nog geen waarde was ingevoerd voor een voorwaarde op basis van een tekenreeks. Als u een staat kiest, wordt de hele regel opnieuw gecompileerd, en de lege waarde kwam tot de vergelijking als de booleaanse waarde `false`. Een voorwaarde zonder waarde wordt nu vergeleken met een lege tekst, en een getal dat is ingevoerd voor een staat, dat een tekenreeks is, wordt als tekst gebruikt\nDe scripteditor laat de adapter nu elke 10 seconden weten dat deze open is, en de adapter houdt de typedefinities en de compiler actief terwijl dat het geval is, dus als u een script opslaat, hoeft u niet te wachten tot ze opnieuw worden gebouwd. 30 seconden na het laatste teken van leven telt de GUI als verdwenen en wordt alles teruggegeven - ongeveer 100 MB. Een tabblad op de achtergrond telt niet als geopend, dus een vergeten browsertabblad kan de herinnering niet dagenlang levend houden (#2373)\nDe typedefinities van Node.js, IOBroker en de geconfigureerde bibliotheken werden bij elke start gelezen, of iemand ze nu wilde of niet. U kunt maar twee dingen doen: een TypeScript-script compileren en de ingebouwde editor, en ze voegen ongeveer 90 MB toe aan de compiler, zodat ze nu worden gelezen wanneer een van hen dat daadwerkelijk vraagt. In een exemplaar dat gewoon JavaScript draait en elders wordt bewerkt (mirror directory, externe editor) worden ze nooit gelezen; de declaraties van globale JavaScripts worden zonder JavaScript gegenereerd en komen op dezelfde manier uit. Ze kunnen ook voorgoed worden uitgeschakeld („Typedefinities laden”, tabblad TypeScript) - de editor wordt dan niet meer automatisch aangevuld en TypeScript-scripts worden niet meer gecompileerd, waarvoor de adapter waarschuwt in het logboek (#2373)\nElke instantie hield twee TypeScript-taaldiensten in leven, of ze nu nodig waren of niet, en elke service had een capaciteit van ongeveer 95 MB toen er iets was gecompileerd. Ze zijn nu alleen gebaseerd op de eerste compilatie, en de declaraties van wereldwijde JavaScripts worden op het scriptobject opgeslagen op dezelfde manier als de gecompileerde TypeScript-bronnen dat al deden, zodat ze na een herstart niet langer opnieuw worden gegenereerd. Wat een taaldienst uiteindelijk bouwt, wordt een minuut na de laatste compilatie opnieuw uitgebracht en op aanvraag opnieuw opgebouwd. Op een testsysteem duurde dit een heap van 241 MB naar 127 MB (352 MB tot 233 MB RSS) (#2373)\nDe helpers die de scripteditor zelf tekent - de rij „Explain/Refactor/Test” boven elke functie, de tooltips voor object-ID's en CRON-expressies, en de suggesties voor inline-code - kunnen worden uitgeschakeld. De instantie-instelling „AI-helpers weergeven in de scripteditor” (AI-instellingen) doet dit; de instelling is standaard ingeschakeld, dus er verandert niets voor iedereen die er tevreden mee is. In `Alt+I` wordt nog steeds de waarde van de object-ID onder de cursor weergegeven als ze uitgeschakeld zijn\nDe redenering van een OpenAI-compatibel eindpunt werd onvoorwaardelijk uitgeschakeld: `reasoning_effort: „none\"` werd bij elk verzoek verzonden zodra een aangepaste basis-URL was geconfigureerd. Dat is goed voor een klein lokaal model en verkeerd voor al het andere - achter een proxy wordt de redenering uitgeschakeld van het model waarvoor men betaalt, of dat wordt afgewezen. Het is nu een instelling („Reasoning effort”), en de standaardinstelling laat de parameter weg en laat het eindpunt beslissen\nDe AI-redacteur vertelde de adapter hoelang hij bereid was te wachten, en de adapter heeft hem nooit gelezen: een vastzittende inline-voltooiing hield de volledige tien minuten vast in plaats van de vijftien seconden waar hij om vroeg\nVoor de inline-voltooiing werd het model gebruikt dat werd gekozen in de AI-chat, maar de provider zelf, zodat een model van de ene provider kon worden aangevraagd met de inloggegevens en op het eindpunt van een andere provider. Model en provider worden nu onthouden en samen gebruikt\nAls twee providers een model met dezelfde naam aanbieden, bijvoorbeeld een proxy en de leverancier die erachter zit, werd besloten wie van hen bediende, door de persoon die het eerst werd geantwoord, en kon van de ene herlaadbeurt naar de andere worden overgeschakeld. De provider die als eerste is geconfigureerd wint nu, dus de directe route heeft de voorkeur boven een proxy",
|
|
127
|
-
"fr": "Règles : un bandeau vide se replie jusqu'au titre. Une règle sans conditions agit sur chaque déclencheur, mais cette bande était la plus haute de la règle : une zone de dépôt avec un sol de 64 pixels, le sélecteur « juste cocher » et une ligne « ou » par groupe, 292 pixels pour rien. Il fait 41 pixels maintenant et dit « sans condition ». Cliquez sur le titre pour l'ouvrir à nouveau, le faire glisser dessus l'ouvre tout seul, et une bande contenant des conditions ne se plie jamais\nRègles : la palette de blocs occupe la moitié de la place. Une entrée comportait 24 pixels de marge autour d'une icône de 30 pixels, soit 66 pixels de barre latérale pour une ligne de texte. Quatre blocs occupaient toute la hauteur et le reste était placé derrière une barre de défilement. Les entrées sont espacées de 31 pixels, les icônes situées au-dessus n'ont plus la même hauteur que les étiquettes, et la barre latérale mesure 168 pixels au lieu de 200 pixels. Un nom trop long affiche le texte intégral en infobulle. Le bouton qui replie la palette se trouve également sur la ligne de la palette, au lieu d'un pixel sur la gauche, où il pendait au-dessus du bord de la fenêtre une fois la palette pliée\nRègles : choisir l'état d'un déclencheur renvoyait l'éditeur avec « n.replace is not a function » alors qu'aucune valeur n'avait encore été saisie. Le choix d'un état recompile la règle complète, et la valeur vide est arrivée à la comparaison sous la forme booléenne « false ». Une condition sans valeur est désormais comparée à un texte vide, et un chiffre saisi pour un état qui est une chaîne est utilisé comme texte\nL'éditeur de script indique désormais à l'adaptateur toutes les 10 secondes qu'il est ouvert, et l'adaptateur garde les définitions de type et le compilateur à chaud. Enregistrer un script ne nécessite donc pas qu'il soit reconstruit. 30 secondes après le dernier signe de vie, l'interface graphique est considérée comme perdue et tout est rendu, soit environ 100 Mo. Un onglet en arrière-plan n'est pas considéré comme ouvert, donc un onglet oublié ne peut pas le garder en mémoire (#2373)\nLes définitions de type de Node.js, IObroker et des bibliothèques configurées étaient lues à chaque démarrage, que cela soit voulu ou non. Il n'y a que deux choses à faire : compiler un script TypeScript et l'éditeur intégré. Ils ajoutent environ 90 Mo au compilateur. Ils sont donc lus dès que l'un d'eux le demande. Une instance qui exécute du JavaScript et qui est modifiée ailleurs (répertoire miroir, éditeur externe) ne les lit jamais ; les déclarations des JavaScript globaux sont générées sans elles et sortent identiques. Ils peuvent aussi être définitivement désactivés (« Charger les définitions de type », onglet TypeScript). L'éditeur perd alors son autocomplétion et les scripts TypeScript ne sont plus compilés, comme l'adaptateur le signale dans le log (#2373)\nChaque instance maintenait deux services linguistiques TypeScript actifs, qu'elle en ait besoin ou non, et chacune conservait environ 95 Mo une fois compilé. Ils ne sont créés que sur la première compilation, et les déclarations des scripts globaux sont stockées dans l'objet de script, de la même manière que les sources TypeScript compilées. Un redémarrage ne les régénère plus. What a language service does end up est réédité une minute après la dernière compilation et reconstruit à la demande. Sur un système de test, il a passé de 241 Mo à 127 Mo (352 Mo à 233 Mo de RSS) (#2373)\nLes aides créées par l'éditeur de script lui-même (la ligne « Expliquer/Refactor/Test » au-dessus de chaque fonction, les info-bulles pour les ID d'objets et les expressions CRON et les suggestions de code en ligne) peuvent être désactivées. Le paramètre d'instance « Afficher les assistants IA dans l'éditeur de script » (paramètres d'IA) le fait ; il est activé par défaut, donc rien ne change pour les satisfaits. `Alt+I` affiche toujours la valeur de l'ID de l'objet sous le curseur éteint\nLe raisonnement d'un point de terminaison compatible avec OpenAI a été désactivé : « reasoning_effort : « none » est envoyé à chaque demande dès qu'une URL de base personnalisée a été configurée. C'est bien pour un petit modèle local et c'est faux pour tout le reste. Un proxy désactive le raisonnement du modèle même pour lequel on paie, ou il est rejeté. C'est un réglage maintenant (« Effort de raisonnement »), et par défaut, c'est le point final qui décide\nL'éditeur d'IA a indiqué à l'adaptateur combien de temps il était prêt à attendre, mais celui-ci ne l'a jamais lu : une page bloquée a tenu sa place pendant dix minutes au lieu des quinze secondes demandées\nLa saisie en ligne a pris le modèle choisi dans le chat IA, mais le fournisseur lui-même. Ainsi, le modèle d'un fournisseur pouvait être demandé avec les informations d'identification et un autre. Le modèle et le fournisseur sont désormais mémorisés\nLorsque deux fournisseurs proposent un modèle du même nom, un proxy et le fournisseur qui le propose, par exemple, celui qui le proposait était décidé en premier, et pouvait changer d'un rechargement à l'autre. Le fournisseur configuré First gagne, donc la route directe est préférée à un proxy",
|
|
128
|
-
"it": "Regole: una banda «e» vuota si piega fino al titolo. Una regola senza condizioni agisce su ogni trigger, ma quella banda era comunque la più alta della regola: un'area di caduta con 64 px, selettore «just check» e una riga «o» per gruppo, 292 px. Ora è di 41 px e dice «senza condizioni», facendo clic sul titolo si apre di nuovo, trascinando una condizione si apre da sola e una banda con condizioni non si piega mai\nRegole: la palette occupa metà dello spazio. Una voce aveva 24 px di padding su un'icona di 30 px, con 66 px di barra laterale per una riga di testo, quattro blocchi e tutto il resto dietro una barra di scorrimento. Le voci ora distano 31 px, le schede con sole icone non hanno più l'altezza di un'etichetta che non hanno e la barra laterale è larga 168 px invece di 200 px. Un nome troppo lungo per avere il testo completo. Il pulsante che ripiega la palette ora si trova anche sulla linea della palette invece di un pixel a sinistra, dove era appeso sul bordo della finestra\nRegole: selezionando lo stato di un trigger, l'editor ha digitato «n.replace is not a function» se una condizione in una stringa non era ancora valida. La scelta di uno stato ricompila l'intera regola e il valore vuoto è booleano `false`. Una condizione senza valore ora si confronta con un testo vuoto e come testo si usa un numero immesso per uno stato che è una stringa\nL'editor di script ora dice all'adattatore ogni 10 secondi che è aperto e mantiene le definizioni dei tipi e il compilatore attivi finché è così, quindi salvare uno script non aspetta che vengano ricreati. 30 secondi dopo l'ultimo segno di vita la GUI conta come sparita e tutto viene restituito: circa 100 MB. Una scheda in background non è aperta, quindi una scheda dimenticata non può durare giorni (#2373)\nLe definizioni dei tipi di Node.js, IOBroker e le librerie configurate venivano lette ad ogni avvio, che lo volesse o no. Solo due cose, compilare uno script TypeScript e l'editor integrato, aggiungono circa 90 MB al compilatore, quindi ora vengono letti quando uno lo chiede. Un'istanza in JavaScript semplice e modificata altrove (mirror directory, editor esterno) non li legge mai; le dichiarazioni di JavaScript globali sono generate senza di esse e sono uguali. Possono anche essere disattivati per sempre («Load type definition», scheda TypeScript): l'editor perde l'autocompletamento e gli script TypeScript non vengono più compilati, cosa che l'adattatore avvisa nel log (#2373)\nOgni istanza manteneva attivi due servizi TypeScript, che ne avesse bisogno o meno, e ognuno conteneva circa 95 MB dopo aver compilato qualcosa. Ora si basano solo sulla prima compilazione e le dichiarazioni dei JavaScript globali sono archiviate nell'oggetto script come già i sorgenti TypeScript compilati, quindi un riavvio non li rigenera più. Ciò che un servizio linguistico crea viene rilasciato un minuto dopo l'ultima compilazione e ricostruito su richiesta. Su un sistema di test ci sono voluti da 241 MB a 127 MB heap (da 352 MB a 233 MB RSS) (#2373)\nGli helper che l'editor di script utilizza da solo, la riga «Explan/Refactor/Test» sopra ogni funzione, i tooltip per ID oggetto ed espressioni CRON e il codice in linea, possono essere disattivati. L'impostazione «Mostra aiutanti AI nell'editor di script» (impostazioni AI) lo fa; è attiva di default, quindi non cambia nulla per chi ne è soddisfatto. `Alt+I` mostra ancora il valore dell'ID oggetto quando sono spenti\nLa logica di un endpoint compatibile con OpenAI è stata disattivata incondizionatamente: «none» è uscito con ogni richiesta non appena è stato configurato un URL di base personalizzato. È giusto per un piccolo modello locale e sbagliato per tutto il resto: dietro un proxy spegne il ragionamento del modello per cui si paga o viene rifiutato. Ora è un'impostazione («Reasoning effort») e di default omette il parametro e decide l'endpoint\nL'editor AI ha detto all'adattatore quanto era disposto ad aspettare e l'adattatore non l'ha mai letto: un completamento in linea bloccato è durato dieci minuti invece dei quindici richiesti\nIl completamento in linea ha utilizzato il modello scelto nella chat AI ma il provider stesso, quindi richiederne uno con le credenziali e l'endpoint di un altro. Modello e fornitore sono ora ricordati e usati insieme\nQuando due provider offrono un modello con lo stesso nome, un proxy e il fornitore dietro, ad esempio, chi lo ha fornito è deciso per primo e può passare da una ricarica all'altra. Il provider configurato per primo vince ora, quindi preferisce il proxy",
|
|
129
|
-
"es": "Reglas: una banda vacía con «y» se dobla hasta su título. Una regla sin condiciones ejecuta sus acciones en cada activación, pero esa banda seguía siendo la más alta de la regla: un área desplegable con un suelo de 64 píxeles, el selector de «solo comprobar» y una fila «o» por grupo, 292 píxeles para nada. Ahora mide 41 píxeles y dice «sin condiciones». Al hacer clic en el encabezado, se abre de nuevo, al arrastrar una condición, se abre sola y una banda con condiciones nunca se dobla\nReglas: la paleta de bloques ocupa la mitad. Una entrada tenía 24 píxeles de relleno alrededor de un icono de 30 píxeles, lo que dejaba 66 píxeles en la barra lateral para una línea de texto. Cuatro bloques llenaban toda la altura y todo lo demás detrás de una barra de desplazamiento. Las entradas están separadas por 31 píxeles, las pestañas de solo iconos ya no tienen el alto de una etiqueta que no tienen y la barra lateral mide 168 píxeles en lugar de 200 píxeles. Un nombre demasiado largo para eso tiene el texto completo. El botón que dobla la paleta también está ahora en la línea de la paleta, en lugar de un píxel a la izquierda, donde colgaba del borde de la ventana una vez doblada la paleta\nReglas: al elegir el estado de un disparador, el editor decía «n.replace no es una función» cuando una condición del estado de la cadena aún no tenía ningún valor. Al elegir un estado, se vuelve a compilar toda la regla y el valor vacío llegó a la comparación como el booleano «falso». Una condición sin valor ahora se compara con un texto vacío y se utiliza como texto un número introducido para un estado, es decir, una cadena\nEl editor de guiones ahora le dice al adaptador cada 10 segundos que está abierto y mantiene las definiciones de tipos y el compilador activos, por lo que guardar un guion no espera a que se vuelva a crear. 30 segundos después de la última señal de vida, la GUI cuenta como agotada y todo se devuelve, unos 100 MB. Una pestaña en segundo plano no cuenta como abierta, por lo que olvidar no puede mantener la memoria viva durante días (#2373)\nLas definiciones de tipos de Node.js, IOBroker y las bibliotecas configuradas se leían al principio, tanto si algo las quería como si no. Solo hay dos cosas, compilar un guion de TypeScript y el editor integrado, y añaden unos 90 MB al compilador, por lo que ahora se leen cuando uno de esos pregunta. Una instancia que ejecuta JavaScript simple y se edita en otro lugar (directorio espejo, editor externo) nunca los lee; las declaraciones de los JavaScript globales se generan sin ellos y salen igual. También se pueden desactivar definitivamente («Cargar definiciones de tipos», pestaña TypeScript). El editor pierde su autocompletado y los guiones de TypeScript ya no se compilan, lo que el adaptador avisa en el registro (#2373)\nCada instancia mantuvo activos dos servicios lingüísticos de TypeScript, los necesitara o no, y cada uno conservó unos 95 MB una vez compilado algo. Ahora se basan únicamente en la primera compilación y las declaraciones de los JavaScript globales se almacenan en el objeto de script de la misma manera que ya lo hacían las fuentes de TypeScript compiladas, por lo que al reiniciarlas ya no las regenera. Lo que un servicio lingüístico acaba creando se publica de nuevo un minuto después del último recopilatorio y se reconstruye a pedido. En un sistema de prueba, una instancia pasó de 241 MB a 127 MB (352 MB a 233 MB RSS) (#2373)\nLos ayudantes que el editor de guiones dibuja por sí solo (la fila «Explicar/Refactor/Probar» sobre cada función, la información de los ID de objetos y las expresiones CRON y las sugerencias de código en línea) se pueden desactivar. El ajuste de instancia «Mostrar ayudantes de IA en el editor de guiones» (ajustes de IA) lo hace; está activado por defecto, así que nada cambia para quien esté contento con ellos. `Alt+I` sigue mostrando el valor del ID del objeto bajo el cursor cuando está desactivado\nEl razonamiento de un punto final compatible con OpenAI se desactivó incondicionalmente: `reasoning_effort: «ninguna» en cada solicitud tan pronto como se configuró una URL base personalizada. Eso es correcto para un modelo local pequeño e incorrecto para todo lo demás. Detrás de un poder se desactiva el razonamiento del mismo modelo por el que se paga o se rechaza. Ahora es un ajuste («Esfuerzo de razonamiento») y por defecto omite el parámetro y deja que el punto final decida\nEl editor de IA le dijo al adaptador cuánto tiempo estaba dispuesto a esperar y el adaptador nunca lo leyó: un atasco al completar en línea mantuvo su espacio durante diez minutos en lugar de los quince segundos que pedía\nLa finalización en línea tomó el modelo elegido en el chat de IA, pero eligió el propio proveedor, por lo que se pudo solicitar el modelo de un proveedor con las credenciales y en el extremo de otro. El modelo y el proveedor ahora se recuerdan y se usan juntos\nCuando dos proveedores ofrecen un modelo con el mismo nombre (un proxy y el proveedor detrás, por ejemplo) cuál de ellos sirve, lo decide el que responde primero y puede cambiar de una recarga a otra. El proveedor configurado primero gana ahora, por lo que se prefiere la ruta directa a un proxy",
|
|
130
|
-
"pl": "Zasady: pusty pasek „i” składa się do nagłówka. Reguła bez warunków uruchamia swoje działania na każdym wyzwalaczu, ale to pasmo nadal było najwyższym elementem reguły - obszar upuszczania z podłogą 64px, selektorem „po prostu sprawdź” i wierszem „lub” na grupę, 292 pikseli za darmo. Ma teraz 41 pikseli i mówi „bez warunku”, kliknięcie nagłówka otwiera go ponownie, przeciągnięcie warunku otwiera go samoistnie, a pasmo, które ma w sobie warunki, nigdy się nie składa\nZasady: paleta bloków zajmuje połowę miejsca, które zrobiła. Wpis zawierał 24px wypełnienia wokół ikony 30 pikseli, która pozostawiła 66 pikseli paska bocznego dla jednej linii tekstu - więc cztery bloki wypełniały całą wysokość, a wszystko inne znajdowało się za paskiem przewijania. Wpisy są teraz oddalone od siebie o 31 pikseli, zakładki tylko ikony nad nimi nie zastrzegają już wysokości etykiety, której nie mają, a pasek boczny ma szerokość 168 pikseli zamiast 200 pikseli. Nazwa zbyt długa na to otrzymuje pełny tekst jako podpowiedź. Przycisk, który składa paletę, znajduje się teraz na linii palety zamiast jednego piksela po lewej stronie, gdzie wisiał nad krawędzią okna po złożeniu palety\nReguły: wybranie stanu wyzwalacza spowodowało usunięcie edytora z „n.replace is not a function”, gdy warunek stanu łańcucha nie miał jeszcze wprowadzonej wartości. Wybór stanu ponownie kompiluje całą regułę, a pusta wartość dotarła do porównania jako logiczna „fałsz”. Warunek bez wartości porównuje się teraz z pustym tekstem, a liczba wprowadzona dla stanu będącego ciągiem jest używana jako jego tekst\nEdytor skryptów informuje teraz adapterowi co 10 sekund, że jest otwarty, a adapter zachowuje definicje typów i kompilator na gorąco, podczas gdy tak jest, więc zapisanie skryptu nie czeka na ich ponowne zbudowanie. 30 sekund po ostatnim znaku życia GUI liczy się jako zniknął i wszystko jest oddane - około 100 MB. Karta w tle nie jest liczona jako otwarta, więc zapomniana karta przeglądarki nie może utrzymać pamięci przy życiu przez wiele dni (#2373)\nDefinicje typów Node.js, ioBroker i skonfigurowanych bibliotek były odczytywane na każdym początku, niezależnie od tego, czy cokolwiek ich chciało, czy nie. Robią się tylko dwie rzeczy - skompilowanie skryptu TypeScript i wbudowany edytor - i dodają około 90 MB do kompilatora, więc są teraz odczytywane, gdy jeden z nich faktycznie poprosi. Instancja, która uruchamia zwykły JavaScript i jest edytowana gdzie indziej (katalog lustrzany, edytor zewnętrzny) nigdy ich nie czyta; deklaracje globalnych JavaScript są generowane bez nich i wychodzą tak samo. Można je również wyłączyć na dobre („Definicje typów obciążenia”, karta TypeScript) - edytor traci wtedy automatyczne uzupełnianie i skrypty TypeScript przestają się kompilować, o czym adapter ostrzega w dzienniku (#2373)\nKażda instancja utrzymywała przy życiu dwie usługi językowe TypeScript, niezależnie od tego, czy ich potrzebowała, czy nie, a każda z nich utrzymywała około 95 MB po skompilowaniu czegokolwiek. Są one teraz zbudowane tylko na pierwszej kompilacji, a deklaracje globalnych skryptów JavaScript są przechowywane w obiekcie skryptu w taki sam sposób, w jaki były już skompilowane źródła TypeScript - więc ponowne uruchomienie ich nie regeneruje. To, co tworzy usługa językowa, zostaje ponownie wydana minutę po ostatniej kompilacji i odbudowana na żądanie. W systemie testowym zajęło to instancję od 241 MB do 127 MB sterty (352 MB do 233 MB RSS) (#2373)\nPomocnicy, których edytor skryptów rysuje samodzielnie - wiersz „Wyjaśnij/ Refactor/Test” nad każdą funkcją, podpowiedzi dla identyfikatorów obiektów i wyrażeń CRON oraz sugestie kodu wbudowanego - można wyłączyć. Ustawienie instancji „Pokaż pomocników AI w edytorze skryptów” (ustawienia AI) robi to; jest domyślnie włączone, więc nic się nie zmienia dla każdego, kto jest z nich zadowolony. `Alt+I` nadal pokazuje wartość identyfikatora obiektu pod kursorem, gdy są wyłączone\nRozumowanie punktu końcowego zgodnego z OpenAI zostało wyłączone bezwarunkowo: `rationing_esforç: „none\"` wychodziło z każdym żądaniem, gdy tylko skonfigurowano niestandardowy bazowy adres URL. Jest to właściwe dla małego modelu lokalnego i złe dla wszystkiego innego - za proxy wyłącza rozumowanie samego modelu, za który się płaci lub jest odrzucony. Jest to ustawienie teraz („Wysiłek rozumowania”), a domyślny parametr pozostawia poza nim i pozwala punktowi końcowi decydować\nEdytor AI powiedział adapterowi, jak długo chce czekać, a adapter nigdy go nie odczytał: zablokowane ukończenie w linii utrzymywało jego gniazdo przez pełne dziesięć minut zamiast piętnaście sekund, o które prosił\nUkończenie wbudowane obejmowało model wybrany na czacie AI, ale wybrało samego dostawcę, więc model jednego dostawcy można było zażądać z poświadczeniami i w punkcie końcowym innego. Model i dostawca są teraz zapamiętywane i używane razem\nKiedy dwóch dostawców oferuje model o tej samej nazwie - na przykład proxy i sprzedawca, który za nim stoi - który z nich obsługiwał, decyduje kto z nich odpowiedział jako pierwszy i może zmienić się z jednego przeładowania na następne. Dostawca skonfigurowany jako pierwszy wygrywa teraz, więc bezpośrednia trasa jest preferowana niż proxy",
|
|
131
|
-
"uk": "Правила: порожня смуга «і» складається до свого заголовка. Правило без умов виконує свої дії на кожному тригері, але ця смуга все ще була найвищою річчю в правилі - область падіння з підлогою 64 пікселів, селектор «просто перевірити» та рядок «або» на групу, 292px даремно. Зараз він 41 піксель і говорить «без умови», натискання заголовка знову відкриває його, перетягування умови відкриває його сама, а смуга, яка має умови, ніколи не згортається\nПравила: блокова палітра займає половину кімнати, яку вона зробила. Запис містив 24 пікселі підкладки навколо піктограми 30 пікселів, яка залишила 66 пікселів бічної панелі для одного рядка тексту - тому чотири блоки заповнювали всю висоту, а все інше було за смугою прокрутки. Тепер записи знаходяться на відстані 31 пікселів один від одного, вкладки, що містять лише піктограми над ними, більше не резервують висоту мітки, яку вони не мають, а бічна панель має ширину 168 пікселів замість 200 пікселів. Назва, занадто довга для цього, отримує повний текст як підказку. Кнопка, яка складається палітру, також знаходиться на лінії палітри тепер замість одного пікселя зліва від неї, де вона висіла над краєм вікна, коли палітра була складена\nПравила: вибір стану тригера знизив редактор з «n.replace не є функцією», коли умова стану рядка ще не ввела значення. Вибір стану повторно компілює все правило, і порожнє значення прийшло до порівняння як булеве `false`. Умова без значення тепер порівнюється з порожнім текстом, а число, введене для стану, який є рядком, використовується як його текст\nТепер редактор сценаріїв повідомляє адаптеру кожні 10 секунд, що він відкритий, а адаптер зберігає визначення типів та компілятор гарячими, поки це так, тому збереження сценарію не чекає їх повторного створення. Через 30 секунд після останньої ознаки життя графічний інтерфейс вважається минулим, і все повертається - близько 100 Мб. Вкладка у фоновому режимі не вважається відкритою, тому забута вкладка браузера не може зберегти пам'ять живою протягом кількох днів (#2373)\nВизначення типів Node.js, IObroker та налаштованих бібліотек читалися при кожному запуску, незалежно від того, хотілося б щось їх чи ні. Виконуються лише дві речі - компіляція сценарію TypeScript та вбудований редактор - і вони додають близько 90 Мб до компілятора, тому тепер вони читаються, коли хтось із них насправді запитає. Екземпляр, який виконує простий JavaScript і редагується в іншому місці (дзеркальний каталог, зовнішній редактор), ніколи не читає їх; оголошення глобальних JavaScript генеруються без них і виходять однаковими. Їх також можна вимкнути назавжди («Визначення типів завантаження», вкладка TypeScript) - редактор потім втрачає автодоповнення, і сценарії TypeScript більше не компілюються, про що адаптер попереджає в журналі (#2373)\nКожен екземпляр підтримував дві мовні служби TypeScript живими незалежно від того, потрібні вони їм чи ні, і кожна з них зберігала близько 95 МБ після того, як вона щось зібрав. Тепер вони побудовані лише на першій компіляції, а оголошення глобальних JavaScripts зберігаються на об'єкті сценарію так само, як вже були скомпільовані джерела TypeScript - тому перезапуск більше не відновлює їх. Те, що в кінцевому підсумку створює мовна служба, знову випускається через хвилину після останньої компіляції та перебудовується на вимогу. У тестовій системі це зайняло екземпляр від 241 МБ до 127 МБ купи (352 МБ до 233 МБ RSS) (#2373)\nДопомічники, які редактор сценаріїв малює самостійно - рядок «Explicate/Refactor/Test» над кожною функцією, підказки для ідентифікаторів об'єктів та виразів CRON та вбудовані пропозиції коду - можна вимкнути. Налаштування екземпляра «Показати помічників AI в редакторі сценаріїв» (налаштування AI) робить це; він увімкнений за замовчуванням, тому нічого не змінюється для тих, хто задоволений ними. `Alt+I` все ще показує значення ідентифікатора об'єкта під курсором, коли вони вимкнені\nМіркування кінцевої точки, сумісної з OpenAI, було вимкнено беззастережно: `ing_efort: «none\"` виходило з кожним запитом, як тільки було налаштовано спеціальну базову URL-адресу. Це правильно для невеликої локальної моделі і неправильно для всього іншого - за проксі він відключає міркування тієї самої моделі, за яку платить, або відхиляється. Зараз це налаштування («Зусилля міркування»), і за замовчуванням залишає параметр поза увагою і дозволяє кінцевій точці вирішити\nРедактор AI розповів адаптеру, як довго він готовий чекати, і адаптер ніколи не читав його: застрягла вбудована комплектація тримала свій слот протягом цілих десяти хвилин замість п'ятнадцяти секунд, які він просив\nВбудоване завершення взяло модель, обрану в чаті AI, але вибрало самого провайдера, тому модель одного постачальника можна було запросити з обліковими даними та в кінцевій точці іншого. Модель та постачальник тепер запам'ятовуються та використовуються разом\nКоли два постачальники пропонують однойменну модель - наприклад, проксі та постачальник, який стоїть за нею, - хто з них обслуговував, це вирішувалось тим, хто відповідав першим, і він може змінюватися від одного перезавантаження до іншого. Постачальник, налаштований першим, виграє зараз, тому прямий маршрут є кращим перед проксі-сервером",
|
|
132
|
-
"zh-cn": "规则:空的 “和” 波段向下折叠到其标题。没有条件的规则会在每个触发器上运行,但是该波段仍然是规则中最高的东西——下拉区域的下限为 64 像素,“只需勾选” 选择器以及每组一个 “或” 行,292px 一无所获。现在是 41px,上面写着 “无条件”,点击标题再次将其打开,将条件拖到标题上方会自行打开,其中有条件的波段永远不会折叠\n规则:方块调色板占用的空间是其空间的一半。一个条目在 30 像素的图标周围有 24 像素的边距,为一行文本留下 66 像素的侧边栏——因此四个方块占据了整个高度,其他所有内容都在滚动条后面。现在,条目相隔 31 像素,上方的纯图标选项卡不再保留它们没有的标签的高度,侧边栏的宽度是 168 像素,而不是 200 像素。如果名称太长,则以全文作为其工具提示。折叠调色板的按钮现在也位于调色板的线条上,而不是调色板左边的一个像素,调色板折叠后它就会悬挂在窗口边缘\n规则:当字符串状态的条件尚未输入任何值时,选择触发器的状态会使编辑器关闭,并显示 “n.replace 不是函数”。选择状态会再次编译整个规则,空值作为布尔值 “false” 得出。现在,没有值的条件与空文本进行比较,并且将为状态输入的字符串数字用作其文本\n现在,脚本编辑器每 10 秒告诉适配器它已打开,在这种情况下,适配器会保持类型定义和编译器处于高温状态,因此保存脚本不会等待它们再次构建。在最后一个生命迹象 30 秒后,GUI 算作消失,所有内容都返还了——大约 100 MB。后台的选项卡不算作已打开,因此被遗忘的浏览器选项卡无法使内存存活数天 (#2373)\n无论是否需要它们,每次启动时都会读取 Node.js、IOBroker 和配置库的类型定义。只有两件事能做——编译 TypeScript 脚本和内置编辑器——它们会为编译器增加大约 90 MB,所以现在当其中一个实际提出要求时,它们就会被读取。运行纯 JavaScript 并在其他地方(镜像目录、外部编辑器)编辑的实例永远不会读取它们;全局 JavaScript 的声明是在没有它们的情况下生成的,输出结果相同。它们也可以永久关闭(“加载类型定义”,TypeScript 选项卡)-然后编辑器会丢失自动完成功能,TypeScript 脚本将无法编译,适配器会在日志中警告这一点 (#2373)\n无论是否需要,每个实例都使两个 TypeScript 语言服务处于活动状态,并且每个实例在编译完任何内容后都会保持大约 95 MB 的容量。它们现在仅建立在第一次编译的基础上,并且全局 JavaScript 的声明存储在脚本对象上,就像编译的 TypeScript 源代码一样,因此重启不会再重新生成它们。语言服务最终构建的内容会在上次编译一分钟后再次发布,并按需重建。在测试系统上,这需要一个从 241 MB 到 127 MB 堆的实例(352 MB 到 233 MB RSS)(#2373)\n脚本编辑器自行绘制的帮助程序——每个函数上方的 “解释/重构/测试” 行、对象 ID 和 CRON 表达式的工具提示以及行内代码建议——可以关闭。实例设置 “在脚本编辑器中显示 AI 助手”(AI 设置)可以做到这一点;它默认处于启用状态,因此任何对它们感到满意的人都不会发生任何变化。当光标关闭时,`Alt+I`仍然在光标下方显示对象 ID 的值\n与OpenAI兼容的终端节点的理由被无条件地关闭了:配置了自定义基础网址后,`reasoning_effort: “无” `即取消了每个请求。这对于小型本地模型来说是对的,对其他所有模式来说都是错误的——在代理服务器的背后,它会掩盖人们为之付出代价的理由,或者被拒绝。现在它是一个设置(“推理工作”),默认设置将参数排除在外,让端点决定\nAI 编辑告诉适配器愿意等待多长时间,但适配器从未读过它:嵌入式完成卡住了整整十分钟,而不是要求的十五秒\n内联完成采用了在 AI 聊天中选择的模型,但选择了提供商本身,因此可以使用证书在另一个提供商的端点请求一个提供商的模型。模型和提供商现已被记住并一起使用\n当两个提供商提供同名模型时(例如代理及其背后的供应商),则由最先回答的人决定,并且可以从一次重新加载更改为下一次重新加载。首先配置的提供商现在获胜,因此直接路由优先于代理"
|
|
133
133
|
}
|
|
134
134
|
},
|
|
135
135
|
"platform": "Javascript/Node.js",
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
},
|
|
187
187
|
"dependencies": [
|
|
188
188
|
{
|
|
189
|
-
"js-controller": ">=7.2.
|
|
189
|
+
"js-controller": ">=7.2.5"
|
|
190
190
|
}
|
|
191
191
|
],
|
|
192
192
|
"globalDependencies": [
|
|
@@ -548,6 +548,8 @@
|
|
|
548
548
|
"gptBaseUrl": "",
|
|
549
549
|
"gptBaseUrlKey": "",
|
|
550
550
|
"aiReasoningEffort": "",
|
|
551
|
+
"aiMaxTokens": 8192,
|
|
552
|
+
"historyVersions": 30,
|
|
551
553
|
"aiEditorHelpers": true,
|
|
552
554
|
"claudeKey": "",
|
|
553
555
|
"geminiKey": "",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.javascript",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.4.0",
|
|
4
4
|
"description": "Rules Engine for ioBroker",
|
|
5
5
|
"author": "bluefox <dogafox@gmail.com>",
|
|
6
6
|
"contributors": [
|
|
@@ -42,15 +42,15 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@iobroker/adapter-core": "^3.4.3",
|
|
45
|
-
"@iobroker/types": "^7.2.
|
|
46
|
-
"@types/node": "^22.20.
|
|
45
|
+
"@iobroker/types": "^7.2.4",
|
|
46
|
+
"@types/node": "^22.20.5",
|
|
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.
|
|
53
|
-
"prettier": "^3.9.
|
|
52
|
+
"nodemailer": "^10.0.14",
|
|
53
|
+
"prettier": "^3.9.9",
|
|
54
54
|
"semver": "^7.8.5",
|
|
55
55
|
"suncalc2": "^1.8.1",
|
|
56
56
|
"typescript": "~6.0.3",
|
|
@@ -65,14 +65,14 @@
|
|
|
65
65
|
"@iobroker/build-tools": "^3.0.3",
|
|
66
66
|
"@iobroker/eslint-config": "^2.3.4",
|
|
67
67
|
"@iobroker/plugin-sentry": "^3.2.1",
|
|
68
|
-
"@iobroker/testing": "^6.
|
|
68
|
+
"@iobroker/testing": "^6.3.0",
|
|
69
69
|
"@tsconfig/node22": "^22.0.6",
|
|
70
70
|
"@types/node-schedule": "^2.1.8",
|
|
71
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.1.
|
|
75
|
+
"jsdom": "^30.1.1",
|
|
76
76
|
"timekeeper": "^2.3.1"
|
|
77
77
|
},
|
|
78
78
|
"bugs": {
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import{An as e,Cr as t,Ct as n,En as r,Er as i,Fn as a,Gt as o,Ht as s,Jn as c,Jt as l,Kt as u,Ln as d,Nn as f,Nr as p,On as m,Or as h,Rn as g,Tt as _,Wt as v,Zn as y,br as b,kr as x,m as S,mt as C,nn as w,or as T,qt as E,sr as D,tn as O,vn as k,wt as A,yn as j}from"./_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-NI-3Uv4e.js";import{t as M}from"./Send-Mdo32jMb.js";import{t as N}from"./vite-preload-helper-CaC3yEL3.js";import{c as ee,o as P,s as F}from"./index-CbQlIKB_.js";import{a as I,c as L,d as R,f as z,h as B,i as V,l as te,m as H,n as U,o as W,p as G,r as ne,s as K,t as q,u as J}from"./AiChatService-QKcpW4jQ.js";import{t as Y}from"./blocklyTheme-CGhU3cEO.js";var X=c(T(`path`,{d:`M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m5 11h-4v4h-2v-4H7v-2h4V7h2v4h4z`}),`AddCircleOutlined`),re=c(T(`path`,{d:`M21.99 4c0-1.1-.89-2-1.99-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4zM17 11h-4v4h-2v-4H7V9h4V5h2v4h4z`}),`AddComment`),ie=c(T(`path`,{d:`M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10h5v-2h-5c-4.34 0-8-3.66-8-8s3.66-8 8-8 8 3.66 8 8v1.43c0 .79-.71 1.57-1.5 1.57s-1.5-.78-1.5-1.57V12c0-2.76-2.24-5-5-5s-5 2.24-5 5 2.24 5 5 5c1.38 0 2.64-.56 3.54-1.47.65.89 1.77 1.47 2.96 1.47 1.97 0 3.5-1.6 3.5-3.57V12c0-5.52-4.48-10-10-10m0 13c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3`}),`AlternateEmail`),ae=c(T(`path`,{d:`M9.01 14H2v2h7.01v3L13 15l-3.99-4zm5.98-1v-3H22V8h-7.01V5L11 9z`}),`CompareArrows`),oe=c(T(`path`,{d:`M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4m0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4`}),`Person`),se=c(T(`path`,{d:`M3 10h11v2H3zm0-4h11v2H3zm0 8h7v2H3zm17.59-2.07-4.25 4.24-2.12-2.12-1.41 1.41L16.34 19 22 13.34z`}),`PlaylistAddCheck`),ce=c(T(`path`,{d:`M20 9V7c0-1.1-.9-2-2-2h-3c0-1.66-1.34-3-3-3S9 3.34 9 5H6c-1.1 0-2 .9-2 2v2c-1.66 0-3 1.34-3 3s1.34 3 3 3v4c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-4c1.66 0 3-1.34 3-3s-1.34-3-3-3M7.5 11.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5S9.83 13 9 13s-1.5-.67-1.5-1.5M16 17H8v-2h8zm-1-4c-.83 0-1.5-.67-1.5-1.5S14.17 10 15 10s1.5.67 1.5 1.5S15.83 13 15 13`}),`SmartToy`);p();var le=[{type:`function`,function:{name:`search_datapoints`,description:`Search ALL ioBroker objects by ID, name, or role — includes states, channels, devices, folders, enums (rooms/functions), adapters, instances, scripts, meta, etc. Returns matching IDs with object type, name, role, unit, and a hasChildren hint for containers. IMPORTANT: Aliases and physical device groupings are usually CHANNELS containing multiple state children (e.g. a motion sensor is often a channel alias.0.Floor.Room.MotionSensor with states ACTUAL, BATTERY, STATE under it). If a channel/device/folder matches your query, call get_object_info on its ID to list its state children. Role-based queries work too: "sensor.motion", "switch.light", "value.temperature".`,parameters:{type:`object`,properties:{query:{type:`string`,description:`Search pattern (case-insensitive substring) - matches against object ID, name, and role. Examples: "bewegungsmelder", "temperature", "sensor.motion", "alias.0", "küche", "zigbee2mqtt.0.lamp".`},max_results:{type:`number`,description:`Maximum number of results to return (default: 20).`},object_type:{type:`string`,description:`Optional filter by object type: "state", "channel", "device", "folder", "enum", "adapter", "instance", "script", "meta", etc. Omit to search every type.`}},required:[`query`]}}},{type:`function`,function:{name:`get_state_value`,description:`Get the current value of an ioBroker state/datapoint. Returns value, timestamp, and acknowledgment flag.`,parameters:{type:`object`,properties:{id:{type:`string`,description:`The full state ID, e.g. "zigbee2mqtt.0.sensor.temperature"`}},required:[`id`]}}},{type:`function`,function:{name:`get_object_info`,description:`Get detailed info about ANY ioBroker object + its full parent hierarchy + direct children. Works for every object type: state, channel, device, folder, adapter, instance, enum, meta, script. Returns: the object itself, parent chain (all non-state ancestors up to the adapter), and — if the object is a container (channel/device/folder/enum/instance/adapter/meta) — the list of direct children with their types, names, roles and units. Use this to navigate the object tree: start from a channel found by search_datapoints, read its children to see the actual state IDs underneath.`,parameters:{type:`object`,properties:{id:{type:`string`,description:`The full object ID, e.g. "zigbee2mqtt.0.0x1234.state", "alias.0.Room.MotionSensor", or "enum.rooms.kitchen".`}},required:[`id`]}}},{type:`function`,function:{name:`search_scripts`,description:`Search through all ioBroker JavaScript/Blockly/Rules scripts. Can search by script name/path OR by content (e.g. find all scripts that use a specific datapoint ID). Returns matching script names, paths, and matching lines.`,parameters:{type:`object`,properties:{query:{type:`string`,description:`Search term - matches against script name, path, AND source code content. Examples: "carport", "zigbee2mqtt.0.lamp.state", "telegram"`},max_results:{type:`number`,description:`Maximum number of scripts to return (default: 10)`}},required:[`query`]}}},{type:`function`,function:{name:`read_script`,description:`Read the full source code of a specific ioBroker script by its ID or path. Use search_scripts first to find the script ID, then read_script to see its complete code.`,parameters:{type:`object`,properties:{id:{type:`string`,description:`The script ID (e.g. "script.js.common.Licht.Carport") or path (e.g. "common/Licht/Carport")`}},required:[`id`]}}},{type:`function`,function:{name:`list_scripts`,description:`List ALL available ioBroker scripts with their names, paths, types (JavaScript/Blockly/TypeScript), and enabled status. Use this to get an overview of all scripts before searching or reading specific ones.`,parameters:{type:`object`,properties:{}}}},{type:`function`,function:{name:`run_script`,description:"Execute a JavaScript or TypeScript snippet in the live ioBroker javascript engine and get back everything it logged. The code runs with the full script API (log, console.*, setState, getState, on, schedule, $, exec, httpGet, …) in VERBOSE mode, so internal operations (setState/getState/subscribe/…) are logged too — ideal for diagnosing behaviour or inspecting values. The snippet runs for a short window and is then automatically STOPPED and fully cleaned up (timers, subscriptions, schedules removed); it does NOT create a persistent script. Use `log(...)` or `console.log(...)` in the code to surface the values you want to inspect. WARNING: side effects are real (e.g. setState changes actual devices) — prefer read-only diagnostics unless the user explicitly asked to change something.",parameters:{type:`object`,properties:{source:{type:`string`,description:`The JavaScript (or TypeScript) source to execute. Log the values you want to inspect via log(...) / console.log(...). Top-level await is supported.`},engineType:{type:`string`,description:`Optional. "TypeScript/ts" to run the code as TypeScript. Defaults to JavaScript.`},timeout:{type:`number`,description:`Optional. Milliseconds to keep the script alive to collect asynchronous logs before it is stopped (default 5000, max 60000). Increase when waiting for timers, subscriptions or HTTP responses.`},logLevel:{type:`string`,description:`Optional minimum severity to return: silly, debug, info, warn, error. Default silly (everything).`}},required:[`source`]}}},{type:`function`,function:{name:`get_editor_selection`,description:`Read what the user has currently selected in the script editor. Returns the selected text and its line/column range, or a message if nothing is selected. Use this when the user refers to "this", "das hier", "the selection", or asks about a specific piece of code they highlighted.`,parameters:{type:`object`,properties:{}}}},{type:`function`,function:{name:`get_editor_content`,description:`Read the full current content of the script editor (may differ from the initial script version if the user has made edits). Use this when you need the live editor state rather than the saved script.`,parameters:{type:`object`,properties:{}}}},{type:`function`,function:{name:`get_cursor_position`,description:`Read the current cursor position (line and column, 1-based) in the script editor.`,parameters:{type:`object`,properties:{}}}},{type:`function`,function:{name:`highlight_text_in_editor`,description:`Search for a literal text in the script editor and select + scroll to it. Returns how many occurrences were found. Use this to draw the user's attention to a specific snippet you are discussing.`,parameters:{type:`object`,properties:{text:{type:`string`,description:`Exact substring to search for (case-sensitive).`}},required:[`text`]}}},{type:`function`,function:{name:`highlight_line_range`,description:`Select and scroll to a range of lines in the editor. Both line numbers are 1-based and inclusive. Use this to show the user which block of code you are referring to.`,parameters:{type:`object`,properties:{start_line:{type:`number`,description:`First line (1-based, inclusive).`},end_line:{type:`number`,description:`Last line (1-based, inclusive).`}},required:[`start_line`,`end_line`]}}},{type:`function`,function:{name:`go_to_line`,description:`Move the cursor to a specific line (and optional column) and scroll that line into view. Use this to navigate the user to a relevant spot.`,parameters:{type:`object`,properties:{line:{type:`number`,description:`1-based line number.`},column:{type:`number`,description:`1-based column (optional, default 1).`}},required:[`line`]}}},{type:`function`,function:{name:`insert_text_at_cursor`,description:`Insert text at the current cursor position in the editor (or replace the current selection if one exists). Use sparingly — prefer returning code in a fenced markdown block so the user can review and smart-apply it. Only use direct insertion when the user explicitly asked you to write something into the editor.`,parameters:{type:`object`,properties:{text:{type:`string`,description:`Text to insert.`}},required:[`text`]}}},{type:`function`,function:{name:`replace_selection`,description:`Replace the currently selected text in the editor with new text. Fails if nothing is selected. Use this to refactor or rewrite a specific highlighted snippet.`,parameters:{type:`object`,properties:{text:{type:`string`,description:`Replacement text.`}},required:[`text`]}}},{type:`function`,function:{name:`get_diagnostics`,description:`Read all active Monaco diagnostics (errors, warnings, info, hints) from the current editor model — this is what shows up as red/yellow squiggles. Use this to find syntax errors, unused variables, missing types, or other editor-reported issues the user might be asking about.`,parameters:{type:`object`,properties:{}}}},{type:`function`,function:{name:`get_document_symbols`,description:`Get the document outline of the current script: all top-level functions, classes, constants, and variables with their line numbers. Use this to understand the structure of a long script or to find where a specific function is defined.`,parameters:{type:`object`,properties:{}}}}];function Z(e){return e&&typeof e==`object`?e.en||e.de||``:e||``}function ue(e,t,n){let r=(n||``).toLowerCase();if(!r)return!1;if(e.toLowerCase().includes(r))return!0;let i=t==null?void 0:t.common;if(!i)return!1;let a=Z(i.name).toLowerCase();if(a&&a.includes(r))return!0;let o=(i.role||``).toLowerCase();return!!(o&&o.includes(r))}async function de(e,t,n=20,r){let i=await I(e),a=r==null?void 0:r.toLowerCase(),o=[],s=Object.keys(i),c=new Set;for(let e of s){let t=e.lastIndexOf(`.`);t>0&&c.add(e.substring(0,t))}for(let e of s){let r=i[e],s=r==null?void 0:r.type;if(!s||a&&s!==a||!ue(e,r,t))continue;let l=r.common,u={id:e,type:s,name:Z(l==null?void 0:l.name)};if(l!=null&&l.role&&(u.role=l.role),s===`state`?(u.stateType=(l==null?void 0:l.type)||``,l!=null&&l.unit&&(u.unit=l.unit)):c.has(e)&&(u.hasChildren=!0),o.push(u),o.length>=n)break}return o.length===0?JSON.stringify({message:`No objects found matching "${t}". Hint: try a role like "sensor.motion" or a partial path.`}):JSON.stringify(o)}async function fe(e,t){try{let n=await e.getState(t);return JSON.stringify(n?{val:n.val,ts:n.ts?new Date(n.ts).toISOString():null,ack:n.ack,from:n.from}:{error:`State '${t}' not found`})}catch{return JSON.stringify({error:`Failed to read state '${t}'`})}}var pe=new Set([`channel`,`device`,`folder`,`adapter`,`instance`,`enum`,`meta`]),me=50;async function he(e,t){try{let r=await e.getObject(t);if(!r)return JSON.stringify({error:`Object '${t}' not found`});let i={id:r._id,type:r.type,common:r.common},a=t.split(`.`),o=[];for(let t=a.length-1;t>=2;t--){let r=a.slice(0,t).join(`.`);try{let t=await e.getObject(r);if(t&&t.type!==`state`){var n;o.push({id:t._id,type:t.type,name:Z((n=t.common)==null?void 0:n.name),common:t.common})}}catch{}}if(o.length>0&&(i.parents=o),pe.has(r.type)){let n=await I(e),r=[],a=`${t}.`,o=!1;for(let e of Object.keys(n))if(e.startsWith(a)&&!e.substring(a.length).includes(`.`)){let t=n[e],i=t==null?void 0:t.common,a={id:e,name:Z(i==null?void 0:i.name),type:(t==null?void 0:t.type)||``};if(i!=null&&i.role&&(a.role=i.role),(t==null?void 0:t.type)===`state`&&i!=null&&i.unit&&(a.unit=i.unit),r.push(a),r.length>=me){o=!0;break}}r.length>0&&(i.children=r,o&&(i.childrenTruncated=!0,i.childrenHint=`Only the first ${me} children are shown. Use search_datapoints with a more specific query or the object_type filter to narrow down.`))}return JSON.stringify(i)}catch{return JSON.stringify({error:`Failed to read object '${t}'`})}}function ge(e){return F(e)||e}function _e(e,t,n=10){let r=t.toLowerCase(),i=[];for(let t of e){let e=t.id.toLowerCase(),a=t.name.toLowerCase(),o=t.id.replace(/^script\.js\./,``).replace(/\./g,`/`),s=t.engineType===`Blockly`||t.engineType===`Rules`,c=e.includes(r)||a.includes(r),l=s?ge(t.source):t.source,u=l.toLowerCase().includes(r);if(c||u){let e={id:t.id,path:o,name:t.name,type:s?`Blockly`:t.engineType.includes(`TypeScript`)?`TypeScript`:`JavaScript`,enabled:t.enabled};if(u){let t=l.split(`
|
|
2
|
-
`),n=[];for(let e=0;e<t.length&&!(t[e].toLowerCase().includes(r)&&(n.push({line:e+1,text:t[e].trim()}),n.length>=5));e++);n.length>0&&(e.matchingLines=n)}if(i.push(e),i.length>=n)break}}return i.length===0?JSON.stringify({message:`No scripts found matching "${t}"`}):JSON.stringify(i)}function ve(e,t){let n=t.replace(/\//g,`.`).toLowerCase(),r=e.find(e=>{let t=e.id.toLowerCase();return t===n||t===`script.js.${n}`||t.endsWith(`.${n}`)});if(!r)return JSON.stringify({error:`Script '${t}' not found. Use search_scripts to find available scripts.`});let i=r.engineType===`Blockly`||r.engineType===`Rules`,a=i?ge(r.source):r.source,o=r.id.replace(/^script\.js\./,``).replace(/\./g,`/`);return JSON.stringify({id:r.id,path:o,name:r.name,type:i?`Blockly`:r.engineType.includes(`TypeScript`)?`TypeScript`:`JavaScript`,enabled:r.enabled,source:a})}function ye(e){let t=e.map(e=>({id:e.id,path:e.id.replace(/^script\.js\./,``).replace(/\./g,`/`),name:e.name,type:e.engineType===`Blockly`||e.engineType===`Rules`?`Blockly`:e.engineType.includes(`TypeScript`)?`TypeScript`:`JavaScript`,enabled:e.enabled}));return JSON.stringify(t)}function Q(){return JSON.stringify({error:`Editor is not available. This tool requires the script editor to be open.`})}async function be(e,t,n){if(!t)return JSON.stringify({error:`No running javascript instance found to execute the script.`});let r=n.source;if(!r||typeof r!=`string`)return JSON.stringify({error:`No source code provided.`});try{var i;let a=await e.sendTo(t,`execute`,{source:r,engineType:n.engineType,timeout:n.timeout,logLevel:n.logLevel});return!a||a.ok===!1?JSON.stringify({error:(a==null?void 0:a.error)||`Execution failed`,logs:(a==null?void 0:a.logs)||[]}):JSON.stringify({engineType:a.engineType,runtime:a.runtime,truncated:a.truncated||!1,logCount:((i=a.logs)==null?void 0:i.length)||0,logs:a.logs||[],output:a.output||``})}catch(e){return JSON.stringify({error:`Failed to execute script: ${e instanceof Error?e.message:String(e)}`})}}async function xe(e,t,n,r,i){let a;try{a=JSON.parse(t.function.arguments)}catch{return JSON.stringify({error:`Invalid arguments: ${t.function.arguments}`})}switch(t.function.name){case`search_datapoints`:return de(e,a.query,a.max_results||20,a.object_type);case`get_state_value`:return fe(e,a.id);case`get_object_info`:return he(e,a.id);case`search_scripts`:return _e(n||[],a.query,a.max_results||10);case`read_script`:return ve(n||[],a.id);case`list_scripts`:return ye(n||[]);case`run_script`:return be(e,i,a);case`get_editor_selection`:{if(!(r!=null&&r.getSelection))return Q();let e=r.getSelection();return JSON.stringify(e||{message:`No text is currently selected in the editor.`})}case`get_editor_content`:return r!=null&&r.getContent?JSON.stringify({content:r.getContent()}):Q();case`get_cursor_position`:{if(!(r!=null&&r.getCursorPosition))return Q();let e=r.getCursorPosition();return JSON.stringify(e||{message:`Editor has no cursor position (not focused).`})}case`highlight_text_in_editor`:{if(!(r!=null&&r.highlightText))return Q();let e=r.highlightText(a.text);return JSON.stringify({matches:e,message:e===0?`Text "${a.text}" was not found in the editor.`:`Highlighted ${e} occurrence(s) of "${a.text}".`})}case`highlight_line_range`:{if(!(r!=null&&r.highlightLineRange))return Q();let e=r.highlightLineRange(a.start_line,a.end_line);return JSON.stringify({success:e,message:e?`Selected lines ${a.start_line}-${a.end_line}.`:`Could not select the requested line range.`})}case`go_to_line`:{if(!(r!=null&&r.goToLine))return Q();let e=r.goToLine(a.line,a.column);return JSON.stringify({success:e,message:e?`Cursor moved to line ${a.line}.`:`Could not move the cursor.`})}case`insert_text_at_cursor`:{if(!(r!=null&&r.insertTextAtCursor))return Q();let e=r.insertTextAtCursor(a.text);return JSON.stringify({success:e,message:e?`Text inserted at cursor.`:`Editor rejected the insertion.`})}case`replace_selection`:{if(!(r!=null&&r.replaceSelection))return Q();let e=r.replaceSelection(a.text);return JSON.stringify({success:e,message:e?`Selection replaced.`:`No text was selected to replace.`})}case`get_diagnostics`:{if(!(r!=null&&r.getDiagnostics))return Q();let e=r.getDiagnostics();return JSON.stringify({count:e.length,diagnostics:e})}case`get_document_symbols`:{if(!(r!=null&&r.getSymbols))return Q();let e=await r.getSymbols();return JSON.stringify({count:e.length,symbols:e})}default:return JSON.stringify({error:`Unknown tool: ${t.function.name}`})}}var Se=0;function Ce(){return`msg_${Date.now()}_${++Se}`}function we(e){let{socket:n,runningInstances:r,currentCode:i,currentLanguage:a,allScripts:o,editorApi:s,currentScriptId:c}=e,l=b((e,t,n)=>e===`none`||!n?null:{range:t,scriptId:c||``,scriptVersion:(i||``).length,kind:e,originalText:n},[c,i]),[u,d]=x(()=>{try{let e=window.localStorage.getItem(`Editor.aiChatMessages`);return e?JSON.parse(e):[]}catch{return[]}}),f=b(e=>{d(t=>{let n=typeof e==`function`?e(t):e,r=n.length>100?n.slice(-100):n;try{window.localStorage.setItem(`Editor.aiChatMessages`,JSON.stringify(r))}catch{try{let e=r.slice(-20);window.localStorage.setItem(`Editor.aiChatMessages`,JSON.stringify(e))}catch{}}return r})},[]),[p,m]=x(!1),[g,_]=x(null),[v,y]=x(window.localStorage.getItem(`Editor.aiChatMode`)||`agent`),C=b(e=>{y(e),window.localStorage.setItem(`Editor.aiChatMode`,e)},[]),[w,T]=x(null),[E,D]=x(window.localStorage.getItem(`openai-model`)||``),[O,k]=x([]),[A,j]=x({}),[M,F]=x(!0),[I,U]=x(null),q=h(null),Y=h(null),X=h(null),re=h(null),ie=b(e=>{D(e),G(e,A[e])},[A]),ae=b(async()=>{F(!0),U(null);try{let e=await R(n,r);if(k(e.models),j(e.providerMap),e.models.length>0){let t=z().model,n=t&&e.models.includes(t)?t:e.models[0];D(n),G(n,e.providerMap[n])}e.errors.length>0&&U(e.errors.join(`; `))}catch(e){U(String(e))}F(!1)},[n,r]);t(()=>{ae()},[ae]);let oe=b(e=>{let t=!1,n=!1,r=[],i=!1,a=/@([\w/äöüÄÖÜß-]+)/g,s;for(;(s=a.exec(e))!==null;){let e=s[1].toLowerCase();if(e===`alle`||e===`all`)t=!0;else if(e===`geräte`||e===`devices`||e===`geraete`)n=!0;else if(i=!0,o&&o.length>0){let e=s[1].replace(/\//g,`.`).toLowerCase(),t=e.split(`.`),n=o.find(n=>{let r=n.id.toLowerCase(),i=r.replace(/^script\.js\./,``);if(i===e||i.endsWith(`.${e}`)||r===`script.js.${e}`)return!0;let a=0;for(let e of t){let t=i.indexOf(e,a);if(t===-1)return!1;a=t+e.length}return!0});if(n)r.push(n.id);else for(let e of t){if(e.length<3)continue;let t=o.filter(t=>t.id.toLowerCase().includes(`.${e}`)||t.name.toLowerCase().includes(e));for(let e of t)r.includes(e.id)||r.push(e.id)}}}return i&&r.length===0&&(t=!0),{cleanMessage:e.replace(/@[\w/äöüÄÖÜß]+\s*/g,``).trim(),mentionedScriptIds:r,includeAll:t,includeDevices:n}},[o]),se=b(async(e,t,s)=>{re.current||=await te(),q.current||=await W(n,r);let c=J(),l=a===`blockly`,u=e||s.length>0,d=`You are an AI assistant for ioBroker JavaScript adapter scripting. Help the user write, debug, and understand ioBroker scripts. Write comments in ${c}. Use the ioBroker JavaScript API correctly.
|
|
3
|
-
|
|
4
|
-
ioBroker object hierarchy: adapter.instance.device.channel.state
|
|
5
|
-
- A "state" is a single datapoint (e.g. zigbee2mqtt.0.0x1234.temperature)
|
|
6
|
-
- A "channel" groups related states (e.g. zigbee2mqtt.0.0x1234 contains temperature, humidity, battery)
|
|
7
|
-
- A "device" groups channels (e.g. zigbee2mqtt.0.0x1234)
|
|
8
|
-
- The channel/device often has the human-readable name (e.g. "Living Room Sensor")
|
|
9
|
-
When looking up info about a datapoint, ALWAYS also check its parent channel/device for the device name and context. Use get_object_info which returns the full parent hierarchy automatically.
|
|
10
|
-
|
|
11
|
-
To verify code or diagnose runtime behaviour, you can use the run_script tool: it executes a JavaScript/TypeScript snippet in the live engine (verbose mode) and returns everything it logged, then auto-stops it. Log the values you want to inspect via log(...) / console.log(...). It runs against the live system, so prefer read-only diagnostics (getState, $, getObject) and only call setState when the user explicitly asked to change something.
|
|
12
|
-
|
|
13
|
-
Available API and syntax rules:
|
|
14
|
-
${re.current}`;if(l&&(d+="\n\nThe user is working in the Blockly visual editor. When asked to create or modify code, respond with Blockly XML in a ```xml code block instead of JavaScript."),(t||e)&&(X.current||=await V(n),d+=`\n\nAvailable smart home devices:\n${JSON.stringify(X.current,null,0)}`),!u&&i){if(l){let e=i.indexOf(`%%BLOCKLY_XML%%`),t=e===-1?i:i.substring(0,e).trim(),n=e===-1?``:i.substring(e+15).trim();d+=`\n\nThe user is working on this Blockly script (currently open in the editor).\n\nGenerated JavaScript (shows the logic):\n\`\`\`javascript\n${t}\n\`\`\``,n&&(d+=`\n\nBlockly XML (use for modifications):\n\`\`\`xml\n${n}\n\`\`\``)}else d+=`\n\nThe user's question is about this script (currently open in the editor, ${a||`javascript`}):\n\`\`\`${a||`javascript`}\n${i}\n\`\`\``}if(e&&o&&o.length>0)d+=`\n\nThe user requested ALL scripts. Search through all of them to answer the question. Always identify WHICH script you describe by its full ID. Scripts may reference datapoint IDs via variables.\n\n${P(o,!0)}`;else if(s.length>0&&o){let e=o.filter(e=>s.includes(e.id));e.length>0&&(d+=`\n\nIMPORTANT: The user is asking about the following script(s). Answer ONLY about these scripts, NOT about the currently open editor tab. Analyze the source code below carefully:\n\n${P(e,!0)}`)}return l&&(d+=`\n\n${K(c)}`),[{role:`system`,content:d}]},[n,r,i,a,o]),ce=b(async e=>{if(!e.trim()||p)return;let t=A[E];if(!t){T(S.t(`Please select a valid model`));return}let i=q.current||await W(n,r);if(q.current=i,!i){T(S.t(`No API keys configured`));return}let o=Object.keys(r)[0];if(!o){T(S.t(`No running javascript instance found`));return}let s=t===`custom`&&i.gptBaseUrl||``,c={id:Ce(),role:`user`,content:e,timestamp:Date.now()},l={id:Ce(),role:`assistant`,content:`⏳ ${S.t(`Generating plan...`)}`,timestamp:Date.now()};f(e=>[...e,c,l]),m(!0),T(null);try{let r=J();X.current||=await V(n);let i=X.current||[],c=`Devices in my smart home:\n${JSON.stringify(i)}\n\nI need a plan for this task: ${e}\n\nAnswer with max 6 lines. Use FULL device IDs from the list above (e.g. zigbee2mqtt.0.0xa4c1383f5ef5fb07.state). No explanation. No reasoning.\n1. IDs: <full IDs from the device list. If a device is not in the list, use TODO_DEVICE_ID as placeholder>\n2. Trigger: <on(id) for state changes OR schedule('min hour * * *') for time-based tasks>\n3. Condition: <when to act>\n4. Actions: <what to set, with full IDs and values. For Telegram use sendTo('telegram.0', 'send', {text: msg})>\n5. Else: <alternative actions or nothing>\n6. Extra: <logging, formatting, etc.>\nValues are boolean (true/false) or numbers, not strings. Use .state not .state_toggle.`,l=await H(n,o,{messages:[{role:`user`,content:c}],model:E,provider:t,baseUrl:s});if(l.error){T(l.error),f(e=>e.slice(0,-2)),m(!1);return}let u=B(l.content||``);f(e=>{let t=[...e],n=t[t.length-1];return(n==null?void 0:n.role)===`assistant`&&(t[t.length-1]={...n,content:`📋 **${S.t(`Plan`)}:**\n${u}`}),t});let d={id:Ce(),role:`assistant`,content:`⏳ ${S.t(`Generating code...`)}`,timestamp:Date.now()};f(e=>[...e,d]);let p=a===`blockly`,h=p?`TASK: ${e}\n\nPLAN:\n${u}\n\nGenerate Blockly XML blocks for this ioBroker automation. Use the exact state IDs from the plan. If the plan contains TODO_DEVICE_ID, keep it as a placeholder. Write comments in ${r}. Put the blocks in a \`\`\`xml code block. You may add a short explanation before or after the XML.`:`TASK: ${e}\n\nPLAN:\n${u}\n\nWrite the ioBroker script. Use the exact state IDs from the plan. If the plan contains TODO_DEVICE_ID, keep it as a placeholder with a comment so the user can fill in the correct ID. Write comments in ${r}. Put the code in a \`\`\`javascript code block. You may add a short explanation before or after the code.`,g=p?K(r):L(r),v=await H(n,o,{messages:[{role:`system`,content:g},{role:`user`,content:h}],model:E,provider:t,baseUrl:s});if(v.error){T(v.error),f(e=>e.slice(0,-1)),m(!1);return}let y=B(v.content||``);f(e=>{let t=[...e],n=t[t.length-1];return(n==null?void 0:n.role)===`assistant`&&(t[t.length-1]={...n,content:y}),t}),_(`${S.t(`devices`)}: ${i.length}`)}catch(e){T(String(e)),f(e=>e.slice(0,-1))}m(!1)},[E,A,p,n,r,a,f]),Z=b(async e=>{if(v===`code`)return ce(e);if(!e.trim()||p)return;let t=A[E];if(!t){T(S.t(`Please select a valid model`));return}let i=q.current||await W(n,r);if(q.current=i,!i){T(S.t(`No API keys configured`));return}let a=Object.keys(r)[0];if(!a){T(S.t(`No running javascript instance found`));return}let c=Y.current;if(Y.current=null,!c)try{var d;let e=s==null||(d=s.getSelection)==null?void 0:d.call(s);e&&e.text&&(c=l(`selection`,e.range,e.text))}catch{}let h={id:Ce(),role:`user`,content:e,timestamp:Date.now(),sourceRange:c},g={id:Ce(),role:`assistant`,content:``,timestamp:Date.now(),sourceRange:c};f(e=>[...e,h,g]),m(!0),T(null);let{cleanMessage:y,mentionedScriptIds:b,includeAll:x,includeDevices:C}=oe(e),w=[];if(x)w.push(`${S.t(`all scripts`)} (${(o==null?void 0:o.length)||0})`);else if(b.length>0){let e=b.map(e=>e.replace(/^script\.js\./,``));w.push(e.join(`, `))}else w.push(S.t(`current script`));C&&w.push(S.t(`devices`)),_(`${S.t(`Context`)}: ${w.join(` + `)}`);let D=await se(x,C,b),O=t===`custom`&&i.gptBaseUrl||``,k=y||e;if(o&&o.length>0){let e=k.match(/\b[\w-]+\.\d+\.[\w.-]+/g);if(e){let t=[];for(let n of new Set(e)){let e=ee(o,n);e.length>0&&t.push(`Datapoint "${n}" is used in:\n${e.map(e=>` - ${e.scriptName} (${e.scriptId}) line ${e.lineNumber}: ${e.usageType} → ${e.line}`).join(`
|
|
15
|
-
`)}`)}t.length>0&&(k+=`\n\n[Automatic analysis results]\n${t.join(`
|
|
16
|
-
|
|
17
|
-
`)}`)}}let j=[...D,...u.filter(e=>e.role!==`system`).map(e=>({role:e.role,content:e.content})),{role:`user`,content:k}],M=v===`agent`;try{let e=[...j];for(let r=0;r<5;r++){let i=await H(n,a,{messages:e,model:E,provider:t,baseUrl:O,...M?{tools:le}:{}});if(i.error){if(M&&r===0&&i.error.toLowerCase().includes(`tool`)){let r=await H(n,a,{messages:e,model:E,provider:t,baseUrl:O});if(r.error)T(r.error),f(e=>e.slice(0,-1));else{let e=B(r.content||``);f(t=>{let n=[...t],r=n[n.length-1];return(r==null?void 0:r.role)===`assistant`&&(n[n.length-1]={...r,content:e}),n})}break}T(i.error),f(e=>e.slice(0,-1));break}let c=i.tool_calls;if((!c||c.length===0)&&M&&i.content){let e=i.content.trim();try{let t=JSON.parse(e);t.name&&t.arguments&&(c=[{id:`text_tool_${Date.now()}`,type:`function`,function:{name:t.name,arguments:JSON.stringify(t.arguments)}}])}catch{}}if(!c||c.length===0){let e=B(i.content||``);f(t=>{let n=[...t],r=n[n.length-1];return(r==null?void 0:r.role)===`assistant`&&(n[n.length-1]={...r,content:e}),n});break}i.tool_calls=c;let l=i.tool_calls.map(e=>{let t={};try{t=JSON.parse(e.function.arguments)}catch{}switch(e.function.name){case`search_datapoints`:return`🔍 ${S.t(`Searching datapoints`)}: "${String(t.query||``)}"`;case`get_state_value`:return`📊 ${S.t(`Reading value`)}: ${String(t.id||``)}`;case`get_object_info`:return`📋 ${S.t(`Loading object info`)}: ${String(t.id||``)}`;case`search_scripts`:return`🔍 ${S.t(`Searching scripts`)}: "${String(t.query||``)}"`;case`read_script`:return`📖 ${S.t(`Reading script`)}: ${String(t.id||``)}`;case`list_scripts`:return`📂 ${S.t(`Loading script list`)}`;default:return`⚙️ ${e.function.name}`}});f(e=>{let t=[...e],n=t[t.length-1];return(n==null?void 0:n.role)===`assistant`&&(t[t.length-1]={...n,content:l.join(`
|
|
18
|
-
`)}),t}),e.push({role:`assistant`,content:i.content||``,tool_calls:i.tool_calls});for(let t of i.tool_calls){let r=await xe(n,t,o,s,a);e.push({role:`tool`,tool_call_id:t.id,content:r})}}}catch(e){T(String(e)),f(e=>e.slice(0,-1))}m(!1)},[E,A,u,p,n,r,se,oe,o,v,ce,f,l,s]),ue=b(()=>{f([]),T(null),m(!1),_(null),ne(),window.localStorage.removeItem(`Editor.aiChatHistory`)},[f]),de=b(async(e,t)=>{let i=A[E];if(!i)return`Error: ${S.t(`Please select a valid model`)}`;let o=q.current||await W(n,r);if(q.current=o,!o)return`Error: ${S.t(`No API keys configured`)}`;let s=Object.keys(r)[0];if(!s)return`Error: ${S.t(`No running javascript instance found`)}`;let c=i===`custom`&&o.gptBaseUrl||``,l=a||`javascript`,u=`You are an assistant for writing ioBroker ${l} scripts. The user will ask a question about a snippet of their code. Match your answer to the question: \n- If they ask for an explanation, description, or "what does this do?", reply with clear prose (a few sentences). Do NOT repeat the code unchanged. \n- If they explicitly ask for a change, refactor, fix, or rewrite, reply with a single fenced \`\`\`${l===`blockly`?`xml`:l}\`\`\` code block containing the full replacement for the selection. You may add one short sentence before or after the block. \n- If they ask something ambiguous or meta (e.g. "is this correct?"), reply in prose first and only include code if proposing a change. \nioBroker globals available in scripts: on, setState, getState, schedule, sendTo, log, createState, setStateDelayed, existsState, httpGet, httpPost.`,d=t?`Code from my editor:\n\n\`\`\`${l===`blockly`?`xml`:l}\n${t}\n\`\`\`\n\n${e}`:e;try{let e=await H(n,s,{messages:[{role:`system`,content:u},{role:`user`,content:d}],model:E,provider:i,baseUrl:c});return e.error?`Error: ${e.error}`:e.content||``}catch(e){return`Error: ${e.message||String(e)}`}},[E,A,r,n,a]);return{messages:u,isLoading:p,error:w,model:E,availableModels:O,modelProviderMap:A,modelsLoading:M,modelsError:I,lastContextInfo:g,mode:v,setMode:C,setModel:ie,sendMessage:Z,triggerAiAction:b(e=>{e.range&&e.code?Y.current=l(e.kind||`codelens`,e.range,e.code):Y.current=null,N(async()=>{let{buildActionPrompt:e}=await import(`./aiPromptBuilder-yTB6N2VT.js`);return{buildActionPrompt:e}},[],import.meta.url).then(({buildActionPrompt:t})=>{let n=t({action:e.action,code:e.code,language:a||`javascript`,diagnostic:e.diagnostic,question:e.question,rangeLabel:e.rangeLabel});n?Z(n):Y.current=null}).catch(()=>{Y.current=null,T(S.t(`Failed to build AI action prompt`))})},[Z,a,l]),askInline:de,clearChat:ue,retryLoadModels:ae}}p();var Te=({code:e,language:r,themeType:i,onInsertCode:a,onShowDiff:o,sourceRange:s})=>{let c=h(null);t(()=>{var t;let n=window.monaco;if(!c.current||!(n!=null&&(t=n.editor)!=null&&t.colorize))return;let a=r===`ts`||r===`typescript`?`typescript`:r||`javascript`;n.editor.colorize(e,a,{theme:i===`dark`?`vs-dark`:`vs`}).then(e=>{c.current&&(c.current.innerHTML=e)})},[e,r,i]);let l=b(()=>{navigator.clipboard.writeText(e)},[e]);return D(u,{sx:{position:`relative`,my:1,borderRadius:1,overflow:`hidden`,border:`1px solid`,borderColor:`divider`},children:[D(u,{sx:{display:`flex`,justifyContent:`space-between`,alignItems:`center`,px:1,py:.5,bgcolor:`action.hover`,borderBottom:`1px solid`,borderColor:`divider`},children:[T(u,{sx:{fontSize:`0.75rem`,color:`text.secondary`,textTransform:`uppercase`},children:r||`javascript`}),D(u,{children:[T(v,{title:S.t(`Copy`),children:T(j,{size:`small`,onClick:l,children:T(n,{sx:{fontSize:16}})})}),a&&T(v,{title:S.t(`Insert into editor`),children:T(j,{size:`small`,onClick:()=>a(e),children:T(X,{sx:{fontSize:16}})})}),o&&T(v,{title:S.t(`Show as diff`),children:T(j,{size:`small`,onClick:()=>o(e,s),children:T(ae,{sx:{fontSize:16}})})})]})]}),T(`pre`,{ref:c,style:{margin:0,padding:`8px 12px`,overflow:`auto`,maxHeight:400,fontSize:`13px`,fontFamily:`'Cascadia Code', 'Fira Code', 'Consolas', monospace`,backgroundColor:i===`dark`?`#1e1e1e`:`#f8f8f8`,color:i===`dark`?`#d4d4d4`:`#333`},children:e})]})};p();var Ee=({xml:e})=>{let n=y(),r=h(null),i=h(null),[a,o]=x(60),s=h(!1);return t(()=>{s.current&&(s.current=!1,requestAnimationFrame(()=>{let e=window.Blockly,t=i.current;e&&t&&(e.svgResize(t),t.scrollCenter())}))},[a]),t(()=>{let t=window.Blockly;if(t&&r.current){i.current&&=(i.current.dispose(),null);try{let a=t.inject(r.current,{readOnly:!0,toolbox:null,trashcan:!1,zoom:{controls:!1,wheel:!1,startScale:1},move:{scrollbars:!1,drag:!1,wheel:!1},sounds:!1,renderer:`thrasos`,theme:Y(n),media:`google-blockly/media/`});i.current=a;let c=e.trim();c.startsWith(`<xml`)||(c=`<xml xmlns="https://developers.google.com/blockly/xml">${c}</xml>`);let l=t.utils.xml.textToDom(c),u=10,d=Array.from(l.querySelectorAll(`:scope > block`));for(let e of d)e.setAttribute(`x`,`10`),e.setAttribute(`y`,String(u)),u+=200;t.Xml.domToWorkspace(l,a);let f=a.getTopBlocks(!1);if(f.length>1){let e=10;for(let t of f){let n=t.getRelativeToSurfaceXY();t.moveBy(10-n.x,e-n.y),e+=t.getHeightWidth().height+20}}let p=a.getBlocksBoundingBox();if(p){let e=p.bottom-p.top+20,t=Math.max(60,Math.ceil(e));s.current=!0,o(t)}}catch{}return()=>{i.current&&=(i.current.dispose(),null)}}},[e,n]),T(u,{ref:r,sx:{width:`100%`,height:a,minHeight:60,borderRadius:1,overflow:`hidden`,border:`1px solid`,borderColor:`divider`}})};p();function De(e){let t=[],n=/```(\w*)\n?([\s\S]*?)```/g,r=0,i;for(;(i=n.exec(e))!==null;){if(i.index>r){let n=e.substring(r,i.index).trim();n&&t.push({type:`text`,content:n})}t.push({type:`code`,content:i[2].trim(),language:i[1]||`javascript`}),r=i.index+i[0].length}if(r<e.length){let n=e.substring(r).trim();n&&t.push({type:`text`,content:n})}return t.length===0&&t.push({type:`text`,content:e}),t}function $(e){let t=[],n=/(\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`)/g,r=0,i,a=0;for(;(i=n.exec(e))!==null;)i.index>r&&t.push(e.substring(r,i.index)),i[2]?t.push(T(`strong`,{children:i[2]},a++)):i[3]?t.push(T(`em`,{children:i[3]},a++)):i[4]&&t.push(T(`code`,{className:`ai-chat-inline-code`,style:{padding:`2px 6px`,borderRadius:4,fontSize:`0.85em`,fontFamily:`'Cascadia Code', 'Fira Code', 'Consolas', monospace`},children:i[4]},a++)),r=i.index+i[0].length;return r<e.length&&t.push(e.substring(r)),t}function Oe(e){return e.trim().startsWith(`|`)&&e.trim().endsWith(`|`)}function ke(e){return/^\|[\s:]*-+[\s:|-]*\|$/.test(e.trim())}function Ae(e,t,n){let r=t.palette.mode===`dark`,i=e=>e.trim().replace(/^\||\|$/g,``).split(`|`).map(e=>e.trim()),a=i(e[0]),o=e.slice(2).map(i);return T(u,{sx:{overflowX:`auto`,my:1},children:D(`table`,{style:{borderCollapse:`collapse`,width:`100%`,fontSize:`0.8rem`,color:t.palette.text.primary},children:[T(`thead`,{children:T(`tr`,{children:a.map((e,n)=>T(`th`,{style:{border:`1px solid ${t.palette.divider}`,padding:`6px 10px`,backgroundColor:r?t.palette.grey[800]:t.palette.grey[100],color:t.palette.text.primary,fontWeight:600,textAlign:`left`},children:$(e)},n))})}),T(`tbody`,{children:o.map((e,n)=>T(`tr`,{style:{backgroundColor:n%2==1?r?t.palette.grey[900]:t.palette.grey[50]:void 0},children:e.map((e,n)=>T(`td`,{style:{border:`1px solid ${t.palette.divider}`,padding:`6px 10px`,color:t.palette.text.primary},children:$(e)},n))},n))})]})},n)}function je(e,t){let n=e.split(`
|
|
19
|
-
`),r=[],i=0,a=0;for(;a<n.length;){let e=n[a].trim();if(e===``){a++;continue}if(/^(-{3,}|\*{3,}|_{3,})$/.test(e)){r.push(T(`hr`,{style:{border:`none`,borderTop:`1px solid ${t.palette.divider}`,margin:`8px 0`}},i++)),a++;continue}let o=e.match(/^(#{1,4})\s+(.+)$/);if(o){let e=o[1].length;r.push(T(`div`,{style:{fontWeight:600,fontSize:[`1.2em`,`1.1em`,`1em`,`0.95em`][e-1],margin:`8px 0 4px`},children:$(o[2])},i++)),a++;continue}if(Oe(e)&&a+1<n.length&&ke(n[a+1].trim())&&a+2<n.length){let e=[n[a],n[a+1]],o=a+2;for(;o<n.length&&Oe(n[o]);)e.push(n[o]),o++;r.push(Ae(e,t,i++)),a=o;continue}if(/^[-*+]\s/.test(e)){let e=[];for(;a<n.length&&/^\s*[-*+]\s/.test(n[a]);)e.push(n[a].replace(/^\s*[-*+]\s/,``).trim()),a++;r.push(T(`ul`,{style:{margin:`4px 0`,paddingLeft:20},children:e.map((e,t)=>T(`li`,{children:$(e)},t))},i++));continue}if(/^\d+[.)]\s/.test(e)){let e=[];for(;a<n.length&&/^\s*\d+[.)]\s/.test(n[a]);)e.push(n[a].replace(/^\s*\d+[.)]\s/,``).trim()),a++;r.push(T(`ol`,{style:{margin:`4px 0`,paddingLeft:20},children:e.map((e,t)=>T(`li`,{children:$(e)},t))},i++));continue}r.push(T(`div`,{children:$(e)},i++)),a++}return r}var Me=({message:e,themeType:t,currentLanguage:n,onInsertCode:r,onShowDiff:a,onApplyCode:o})=>{let s=e.role===`user`,c=E(),d=s?t===`dark`?c.palette.primary.dark:c.palette.primary.main:t===`dark`?c.palette.secondary.dark:c.palette.secondary.main,f=c.palette.getContrastText(d),p=i(()=>De(e.content),[e.content]),m=(e,t)=>!!(e===`xml`||e===`blockly`||n===`blockly`&&t&&/<block\s+type=/.test(t));return D(u,{sx:{display:`flex`,gap:1,px:1.5,py:1,mx:.75,my:.5,bgcolor:s?t===`dark`?`rgba(144, 202, 249, 0.10)`:`rgba(25, 118, 210, 0.07)`:t===`dark`?`rgba(206, 147, 216, 0.10)`:`rgba(156, 39, 176, 0.06)`,borderRadius:1.5,borderLeft:`3px solid`,borderLeftColor:d,transition:`background-color 120ms`,"&:hover":{bgcolor:s?t===`dark`?`rgba(144, 202, 249, 0.16)`:`rgba(25, 118, 210, 0.12)`:t===`dark`?`rgba(206, 147, 216, 0.16)`:`rgba(156, 39, 176, 0.10)`}},children:[T(g,{sx:{width:28,height:28,bgcolor:d,color:f,flexShrink:0,mt:.5},children:T(s?oe:ce,{sx:{fontSize:18}})}),T(u,{sx:{flex:1,minWidth:0,fontSize:`0.875rem`,lineHeight:1.6},children:p.map((n,i)=>n.type===`code`?m(n.language,n.content)?D(u,{sx:{my:1},children:[T(Ee,{xml:n.content}),D(u,{sx:{display:`flex`,gap:.5,mt:.5},children:[o&&T(l,{size:`small`,variant:`contained`,color:`primary`,startIcon:T(se,{sx:{fontSize:14}}),onClick:()=>o(n.content),sx:{textTransform:`none`,fontSize:`0.75rem`},children:S.t(`Apply blocks`)}),r&&T(l,{size:`small`,variant:`outlined`,startIcon:T(X,{sx:{fontSize:14}}),onClick:()=>r(n.content),sx:{textTransform:`none`,fontSize:`0.75rem`},children:S.t(`Insert blocks`)})]})]},i):T(Te,{code:n.content,language:n.language||`javascript`,themeType:t,onInsertCode:r,onShowDiff:a,sourceRange:e.sourceRange||null},i):T(u,{sx:{wordBreak:`break-word`,color:c.palette.text.primary},children:je(n.content,c)},i))})]})};function Ne(e){let t=(e||``).toLowerCase();return t.includes(`blockly`)||t.includes(`rules`)?`blockly`:t.includes(`typescript`)?`typescript`:`javascript`}function Pe(e,t){return`\`\`\`${t===`blockly`?`xml`:t}\n${e}\n\`\`\``}function Fe(e){let t=(e.code||``).trim(),n=Ne(e.language),r=e.rangeLabel?` (${e.rangeLabel})`:``;switch(e.action){case`explain`:return t?[`Please explain what this ioBroker ${n} code does${r}.`,`Focus on: which datapoints it reads/writes, which triggers fire it, and any side-effects.`,``,Pe(t,n)].join(`
|
|
20
|
-
`):null;case`refactor`:return t?[`Refactor this ioBroker ${n} code${r} to be cleaner and more idiomatic.`,`Preserve behavior exactly. Keep ioBroker APIs (on, setState, getState, schedule, sendTo, log).`,`Return the full refactored block inside a \`\`\`${n===`blockly`?`xml`:n}\`\`\` code block so it can be smart-applied.`,``,Pe(t,n)].join(`
|
|
21
|
-
`):null;case`comment`:return t?[`Add clear, concise inline comments to this ioBroker ${n} code${r}.`,`Only add comments where they add real value (non-obvious logic, tricky edge cases, business rules).`,`Do not over-comment trivial lines. Return the commented version in a code block.`,``,Pe(t,n)].join(`
|
|
22
|
-
`):null;case`fix`:{if(!t)return null;let i=(e.diagnostic||``).trim();return[`This ioBroker ${n} code has an issue${r}. Please fix it and return the corrected code.${i?`\nReported problem: ${i}`:``}`,`Keep the fix minimal — do not rewrite unrelated parts.`,``,Pe(t,n)].join(`
|
|
23
|
-
`)}case`tests`:return t?[`Suggest how to test this ioBroker ${n} script manually inside the ioBroker admin UI${r}.`,``,"ioBroker scripts run inside the adapter sandbox and CANNOT be unit-tested with Jest, Mocha, or any external test framework. Do NOT propose Jest/Mocha tests, do NOT propose extracting the code into a separate Node.js project, do NOT write `describe` / `test` blocks.",``,`Instead, propose a short list of manual test cases. For each case describe:`,` • Setup — which ioBroker datapoints to prepare and to which values (via the objects tree "Values" tab)`,` • Action — what to trigger: set a state with setState, wait for a schedule, change a sensor value, etc.`,` • Expected — what should happen afterwards: which states should change, what should appear in the adapter log (javascript.0), which side effects are visible`,``,`Keep it concise: 3-6 cases covering the happy path, typical edge cases, and any guard conditions the script has.`,``,Pe(t,n)].join(`
|
|
24
|
-
`):null;case`ask`:{let i=(e.question||``).trim();return i?t?[`Regarding this ioBroker ${n} code${r}:`,``,Pe(t,n),``,i].join(`
|
|
25
|
-
`):i:null}default:return null}}function Ie(e){let t=(e||``).trimStart();if(!t.startsWith(`/`))return null;let n=t.match(/^\/(\w+)(?:\s+([\s\S]*))?$/);if(!n)return null;let r=n[1].toLowerCase(),i=(n[2]||``).trim(),a={explain:`explain`,erklaere:`explain`,erklaeren:`explain`,refactor:`refactor`,refaktor:`refactor`,refaktoriere:`refactor`,comment:`comment`,comments:`comment`,kommentar:`comment`,kommentiere:`comment`,fix:`fix`,fixme:`fix`,tests:`tests`,test:`tests`,ask:`ask`,frag:`ask`,frage:`ask`}[r];return a?{action:a,rest:i}:null}p();function Le(){return[{id:`@all`,label:S.t(`mention @all`),descriptionKey:`All scripts`},{id:`@devices`,label:S.t(`mention @devices`),descriptionKey:`Smart home devices`}]}function Re({provider:e,isDark:t}){return U[e]?T(`img`,{src:`./img/${e}.svg`,alt:e,style:{...q,...t?{filter:`invert(0.85)`}:{}},onError:e=>{e.target.style.display=`none`}}):null}function ze(){try{let e=window.localStorage.getItem(`Editor.aiChatHistory`);return e?JSON.parse(e):[]}catch{return[]}}var Be=({onSend:n,disabled:c,themeType:l,hasSelection:p,selectionText:g,allScripts:_,model:y,availableModels:C,modelProviderMap:w,modelsLoading:E,onModelChange:k,mode:N,onModeChange:ee,currentLanguage:P})=>{let[F,I]=x(``),[L,R]=x(!1),[z,B]=x(``),[V,te]=x(0),H=h(null),U=h(-1),W=h(ze()),G=h(-1),ne=h(``),K=i(()=>{let e=Le().map(e=>({...e,description:S.t(e.descriptionKey)}));if(_)for(let t of _){let n=t.id.replace(/^script\.js\./,``).replace(/\./g,`/`);e.push({id:`@${n}`,label:`@${n}`,description:`${t.name} [${t.enabled?`active`:`inactive`}]`})}return e},[_]),q=i(()=>{if(!z)return K;let e=z.toLowerCase();return K.filter(t=>t.id.toLowerCase().includes(e)||t.description.toLowerCase().includes(e))},[K,z]);t(()=>{te(0)},[z]);let J=b(()=>{let e=F.trim();if(!e||c)return;let t=e,r=Ie(e);if(r){let e=p&&g?g:``,n=Fe({action:r.action,code:e,language:P||`javascript`,question:r.action===`ask`?r.rest:void 0,diagnostic:r.action===`fix`&&r.rest||void 0});n&&(t=n)}else p&&g&&(t=`[Selected code in editor]\n\`\`\`\n${g}\n\`\`\`\n\n${e}`);W.current.push(e),G.current=-1,ne.current=``;try{let e=W.current.slice(-50);window.localStorage.setItem(`Editor.aiChatHistory`,JSON.stringify(e))}catch{}n(t),I(``),R(!1),requestAnimationFrame(()=>{var e;return(e=H.current)==null?void 0:e.focus()})},[F,c,n,p,g,P]),Y=b(e=>{let t=U.current,n=H.current;if(t<0){let t=F?`${F}${e} `:`${e} `;I(t),R(!1),B(``),setTimeout(()=>{n&&(n.focus(),n.setSelectionRange(t.length,t.length))},0);return}let r=F.substring(0,t),i=(n==null?void 0:n.selectionStart)??F.length,a=`${r}${e} ${F.substring(i)}`;I(a),R(!1),B(``),U.current=-1,setTimeout(()=>{if(n){let t=r.length+e.length+1;n.focus(),n.setSelectionRange(t,t)}},0)},[F]),X=b(()=>{U.current=-1,B(``),R(e=>!e)},[]),re=b(e=>{let t=e.target.value;I(t);let n=e.target.selectionStart??t.length,r=t.substring(0,n).match(/@([\w/äöüÄÖÜß]*)$/);r?(U.current=n-r[0].length,B(r[1]),R(!0)):(R(!1),B(``))},[]),ae=b(e=>{if(L&&q.length>0){if(e.key===`ArrowDown`){e.preventDefault(),te(e=>(e+1)%q.length);return}if(e.key===`ArrowUp`){e.preventDefault(),te(e=>(e-1+q.length)%q.length);return}if(e.key===`Enter`||e.key===`Tab`){e.preventDefault(),Y(q[V].id);return}if(e.key===`Escape`){e.preventDefault(),R(!1);return}}if(e.key===`ArrowUp`&&!L&&W.current.length>0){let t=H.current,n=!t||t.selectionStart===0,r=!F.includes(`
|
|
26
|
-
`);if(n&&r){e.preventDefault(),G.current===-1?(ne.current=F,G.current=W.current.length-1):G.current>0&&G.current--,I(W.current[G.current]);return}}if(e.key===`ArrowDown`&&!L&&G.current>=0){let t=H.current,n=!t||t.selectionStart===F.length,r=!F.includes(`
|
|
27
|
-
`);if(n&&r){e.preventDefault(),G.current<W.current.length-1?(G.current++,I(W.current[G.current])):(G.current=-1,I(ne.current));return}}e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),J())},[J,L,q,V,Y,F]);return D(u,{sx:{borderTop:`1px solid`,borderColor:`divider`,position:`relative`},children:[L&&q.length>0&&T(a,{elevation:4,sx:{position:`absolute`,bottom:`100%`,left:8,right:8,maxHeight:200,overflow:`auto`,zIndex:10,mb:.5},children:T(r,{dense:!0,disablePadding:!0,children:q.slice(0,15).map((t,n)=>T(m,{selected:n===V,onClick:()=>Y(t.id),sx:{py:.25,minHeight:32},children:T(e,{primary:t.label,secondary:t.description,slotProps:{primary:{sx:{fontSize:`0.8rem`,fontWeight:500}},secondary:{sx:{fontSize:`0.7rem`}}}})},t.id))})}),N===`code`&&T(O,{label:`${S.t(`mention @devices`)} — ${S.t(`Smart home devices`)}`,size:`small`,variant:`outlined`,sx:{mx:1,mt:.5,maxWidth:`calc(100% - 16px)`}}),p&&g&&T(O,{icon:T(A,{sx:{fontSize:14}}),label:S.t(`Selected code as context`),size:`small`,variant:`outlined`,sx:{mx:1,mt:.5,maxWidth:`calc(100% - 16px)`}}),D(u,{sx:{mx:1,mt:.5,mb:.5,border:`1px solid`,borderColor:`divider`,borderRadius:1.5,overflow:`hidden`,"&:focus-within":{borderColor:`primary.main`}},children:[T(s,{inputRef:H,fullWidth:!0,multiline:!0,maxRows:6,placeholder:S.t(`Ask about your script...`),value:F,onChange:re,onKeyDown:ae,disabled:c,onBlur:()=>{setTimeout(()=>R(!1),200)},variant:`standard`,slotProps:{input:{disableUnderline:!0}},sx:{px:1.5,pt:1,pb:.5,"& .MuiInputBase-root":{fontSize:`0.875rem`}}}),D(u,{sx:{display:`flex`,alignItems:`center`,gap:.75,px:1,pb:.5},children:[T(v,{title:D(u,{sx:{fontSize:`0.8rem`,lineHeight:1.5,maxWidth:360},children:[T(u,{sx:{fontWeight:600,mb:.75},children:S.t(`AI chat mode`)}),D(u,{sx:{mb:.75},children:[D(`strong`,{children:[`💬 `,S.t(`Chat`)]}),` —`,` `,S.t(`Plain conversation. Use for questions, explanations, syntax help. Does not read or modify your scripts.`)]}),D(u,{sx:{mb:.75},children:[D(`strong`,{children:[`🤖 `,S.t(`Agent`)]}),` —`,` `,S.t(`For larger models with tool support. The AI can read, create, and edit scripts, look up datapoints, and browse the object tree — useful for "create a script that...", "which scripts use this state?" or "analyze my light script".`)]}),D(u,{children:[D(`strong`,{children:[`💻 `,S.t(`Code`)]}),` —`,` `,S.t(`For smaller models without tool support. Two-step script generator (plan then code) — useful for "create a script that..." or "write a Blockly rule for...". Output goes into the editor for smart-apply.`)]})]}),enterDelay:400,placement:`left`,children:D(d,{value:N,onChange:e=>ee(e.target.value),size:`small`,variant:`standard`,disableUnderline:!0,sx:{fontSize:`0.7rem`,color:`text.secondary`,border:`1px solid`,borderColor:`text.secondary`,borderRadius:3,bgcolor:`action.hover`,px:.75,"&:hover":{borderColor:`text.disabled`,bgcolor:`action.hover`},"& .MuiSelect-select":{py:`2px`,pr:`18px !important`,display:`flex`,alignItems:`center`,gap:.5}},children:[T(f,{value:`chat`,sx:{fontSize:`0.75rem`},title:S.t(`Plain conversation. Best for: general questions, syntax help, concept explanations.`),children:`💬 Chat`}),T(f,{value:`agent`,sx:{fontSize:`0.75rem`},title:S.t(`For larger models with tool support. Best for: creating, editing, or analyzing scripts; finding datapoint usages; inspecting the object tree.`),children:`🤖 Agent`}),T(f,{value:`code`,sx:{fontSize:`0.75rem`},title:S.t(`For smaller models without tool support. Best for: creating new JavaScript/TypeScript or Blockly scripts from a description.`),children:`💻 Code`})]})}),T(d,{value:y,onChange:e=>k(e.target.value),size:`small`,disabled:E||C.length===0,variant:`standard`,disableUnderline:!0,sx:{fontSize:`0.7rem`,color:`text.secondary`,border:`1px solid`,borderColor:`text.secondary`,borderRadius:3,bgcolor:`action.hover`,px:.75,"&:hover":{borderColor:`text.disabled`,bgcolor:`action.hover`},"& .MuiSelect-select":{py:`2px`,pr:`18px !important`,display:`flex`,alignItems:`center`,gap:.5}},children:C.map(e=>D(f,{value:e,sx:{fontSize:`0.75rem`,display:`flex`,gap:.5},children:[T(Re,{provider:w[e],isDark:l===`dark`}),e]},e))}),T(v,{title:S.t(`Mention scripts as context for the AI. Use @all for all scripts or @scriptName for a specific one.`),enterDelay:500,children:T(j,{size:`small`,onClick:X,sx:{p:`3px`,color:L?`primary.main`:`text.secondary`,border:`1px solid`,borderColor:L?`primary.main`:`text.secondary`,bgcolor:L?void 0:`action.hover`,borderRadius:3,"&:hover":{borderColor:`text.disabled`,bgcolor:`action.hover`}},children:T(ie,{sx:{fontSize:16}})})}),T(u,{sx:{flex:1}}),D(o,{variant:`caption`,sx:{color:`text.disabled`,fontSize:`0.65rem`,mr:.5,whiteSpace:`nowrap`},children:[`Enter `,S.t(`to send`)]}),T(v,{title:`${S.t(`Send`)} (Enter)`,children:T(`span`,{children:T(j,{color:`primary`,onClick:J,disabled:c||!F.trim(),size:`small`,sx:{p:.25},children:T(M,{sx:{fontSize:18}})})})})]})]})]})};p();var Ve=({socket:e,runningInstances:n,themeType:r,currentCode:a,currentLanguage:s,selectedCode:c,allScripts:l,editorApi:d,aiActionRequest:f,onAiActionConsumed:p,onRegisterInlineAsk:m,onInsertCode:g,onShowDiff:y,onApplyCode:x,currentScriptId:E,onClose:O})=>{var A;let M=h(null),{messages:N,isLoading:ee,error:P,model:F,availableModels:I,modelProviderMap:L,modelsLoading:R,modelsError:z,lastContextInfo:B,mode:V,setMode:te,setModel:H,sendMessage:U,triggerAiAction:W,askInline:G,clearChat:ne,retryLoadModels:K}=we(i(()=>({socket:e,runningInstances:n,currentCode:a,currentLanguage:s,allScripts:l,editorApi:d,currentScriptId:E}),[e,n,a,s,l,d,E]));t(()=>(m==null||m(G),()=>m==null?void 0:m(null)),[G,m]);let q=h(null);t(()=>{f&&q.current!==f&&(q.current=f,W(f),p==null||p())},[f,W,p]),t(()=>{var e;(e=M.current)==null||e.scrollIntoView({behavior:`smooth`})},[N]);let J=b(e=>{g==null||g(e)},[g]),Y=b((e,t)=>{y==null||y(e,t)},[y]),X=b(e=>{x==null||x(e)},[x]);return D(u,{sx:{display:`flex`,flexDirection:`column`,height:`100%`,bgcolor:`background.default`,"& .ai-chat-inline-code":{backgroundColor:`action.selected`,color:`text.primary`,border:`1px solid`,borderColor:`divider`}},children:[D(u,{sx:{display:`flex`,alignItems:`center`,gap:1,px:1,py:.5,borderBottom:`1px solid`,borderColor:`divider`,bgcolor:r===`dark`?`grey.900`:`grey.100`,flexShrink:0},children:[T(o,{variant:`subtitle2`,sx:{fontWeight:600,flex:1,color:`text.primary`},children:S.t(`AI Chat`)}),R&&T(w,{size:16}),T(v,{title:S.t(`New chat`),children:T(j,{size:`small`,onClick:ne,children:T(re,{sx:{fontSize:18}})})}),T(v,{title:S.t(`Close`),children:T(j,{size:`small`,onClick:O,children:T(_,{sx:{fontSize:18}})})})]}),(P||z)&&T(k,{severity:`error`,sx:{m:1,py:0},action:z?T(j,{size:`small`,onClick:K,children:T(C,{sx:{fontSize:16}})}):void 0,children:P||z}),B&&T(o,{variant:`caption`,sx:{px:1.5,py:.25,color:`text.secondary`,fontSize:`0.7rem`,bgcolor:`action.hover`,borderBottom:`1px solid`,borderColor:`divider`,flexShrink:0},children:B}),D(u,{sx:{flex:1,overflow:`auto`,py:1},children:[N.length===0&&!ee&&D(u,{sx:{display:`flex`,flexDirection:`column`,alignItems:`center`,justifyContent:`center`,height:`100%`,color:`text.secondary`,px:3,textAlign:`center`},children:[T(o,{variant:`body2`,sx:{mb:1},children:S.t(`Ask questions about your script, request changes, or generate new code.`)}),D(o,{variant:`caption`,color:`text.disabled`,children:[`Enter `,S.t(`to send`),`, Shift+Enter `,S.t(`for new line`)]})]}),N.filter(e=>e.role!==`system`).map(e=>T(Me,{message:e,themeType:r,currentLanguage:s,onInsertCode:J,onShowDiff:Y,onApplyCode:X},e.id)),ee&&((A=N[N.length-1])==null?void 0:A.content)===``&&D(u,{sx:{display:`flex`,alignItems:`center`,gap:1,px:2,py:1},children:[T(w,{size:16}),T(o,{variant:`caption`,color:`text.secondary`,children:S.t(`Thinking...`)})]}),T(`div`,{ref:M})]}),T(Be,{onSend:U,disabled:ee||I.length===0,themeType:r,hasSelection:!!c,selectionText:c,allScripts:l,model:F,availableModels:I,modelProviderMap:L,modelsLoading:R,onModelChange:H,mode:V,onModeChange:te,currentLanguage:s})]})};export{Ve as default,Ie as n,Fe as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Cr as e,Dt as t,Gt as n,Jt as r,Kt as i,Nr as a,Or as o,Tt as s,Ut as c,br as l,m as u,or as d,sr as f}from"./_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-NI-3Uv4e.js";import{n as p}from"./loadMonaco-BVOEahNw.js";a();var m=({originalCode:a,modifiedCode:m,language:h,themeType:g,onAccept:_,onReject:v})=>{let y=o(null),b=o(null),x=o(null);e(()=>{let e=null,t=!1;return p().then(n=>{if(t||!y.current)return;let r=n.editor.createDiffEditor(y.current,{readOnly:!1,originalEditable:!1,renderSideBySide:!0,automaticLayout:!0,theme:g===`dark`?`vs-dark`:`vs`,scrollBeyondLastLine:!1,minimap:{enabled:!1}}),i=n.editor.createModel(a,h),o=n.editor.createModel(m,h);x.current=o,r.setModel({original:i,modified:o}),b.current=r,e=()=>{r.dispose(),i.dispose(),o.dispose(),b.current=null,x.current=null}}).catch(e=>console.error(`Cannot load the code editor: ${e}`)),()=>{t=!0,e==null||e()}},[a,m,h,g]);let S=l(()=>{var e;_(((e=x.current)==null?void 0:e.getValue())||m)},[m,_]);return f(i,{sx:{display:`flex`,flexDirection:`column`,height:`100%`,width:`100%`},children:[f(c,{variant:`dense`,sx:{minHeight:36,bgcolor:`background.paper`,borderBottom:`1px solid`,borderColor:`divider`,gap:1,flexShrink:0},children:[d(n,{variant:`subtitle2`,sx:{flex:1},children:u.t(`AI suggested changes`)}),d(r,{variant:`contained`,color:`success`,size:`small`,startIcon:d(t,{}),onClick:S,children:u.t(`Accept`)}),d(r,{variant:`outlined`,color:`error`,size:`small`,startIcon:d(s,{}),onClick:v,children:u.t(`Reject`)})]}),d(i,{ref:y,sx:{flex:1,overflow:`hidden`}})]})};export{m as default};
|