iobroker.javascript 9.1.1 → 9.2.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 +14 -7
- package/admin/assets/AiChatPanel-sgt697A2.js +296 -0
- package/admin/assets/AiDatapointProvider-B0i3I5Fm.js +2 -0
- package/admin/assets/AiDiffView-RPozjjHf.js +1 -0
- package/admin/assets/AiInlineProvider-Dd7eKxk4.js +7 -0
- package/admin/assets/{Save-Cld9qv9i.js → Save-CkuNSiWL.js} +1 -1
- package/admin/assets/{ScriptEditor-C-fO5h68.js → ScriptEditor-CH4qJzqq.js} +2 -2
- package/admin/assets/ScriptEditorVanillaMonaco-cB_90T0P.js +1 -0
- package/admin/assets/{createSvgIcon-DPvF8xqu.js → createSvgIcon-DYs_tNrE.js} +1 -1
- package/admin/assets/docs-compact-CKNGiYh2.js +336 -0
- package/admin/assets/{index-DFZipply.js → index-BI3JsAz_.js} +1 -1
- package/admin/assets/{index-BVPl8hv0.js → index-DAkyON1r.js} +5 -5
- package/admin/assets/index-DW5CwIma.js +1256 -0
- package/admin/assets/index-SHs7_wDh.js +1 -0
- package/admin/assets/{index-DlDUIfpA.js → index-dN73sbyQ.js} +1 -1
- package/admin/assets/index-hwplVCgv.js +986 -0
- package/admin/assets/index-wHNMOf-c.js +5 -0
- package/admin/assets/inheritsLoose-CIXm_zPk.js +29 -0
- package/admin/assets/{iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-QWG5Arqe.js → iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-CV1_X-Lf.js} +1 -1
- package/admin/assets/{localSharedImportMap-xmSu9Qkg.js → localSharedImportMap-CqvxvyGG.js} +1 -1
- package/admin/assets/useTheme-DuTJsNQ-.js +1 -0
- package/admin/assets/{virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-D-eF6r8M.js → virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-BJ03G6Pu.js} +2 -2
- package/admin/custom/assets/{Components-B8x6wOMD.js → Components-B9ZyjeRI.js} +1 -1
- package/admin/custom/assets/{index-N2n19KrF.js → index-BVwMgafs.js} +1 -1
- package/admin/custom/assets/index-CVIpIckw.js +960 -0
- package/admin/custom/assets/{index-DbXK0odl.js → index-DsIn9jH_.js} +1 -1
- package/admin/custom/assets/{localSharedImportMap-2Enh8EZe.js → localSharedImportMap-C4qXtGUd.js} +1 -1
- package/admin/custom/assets/{virtualExposes-CqrW7o8v.js → virtualExposes-jSvr-kK3.js} +1 -1
- package/admin/custom/assets/{virtual_mf-REMOTE_ENTRY_ID_ConfigCustomJavascriptSet__customComponents_js-BZZsMeVW.js → virtual_mf-REMOTE_ENTRY_ID_ConfigCustomJavascriptSet__customComponents_js-DFSXB0v2.js} +2 -2
- package/admin/custom/customComponents.js +1 -1
- package/admin/google-blockly/own/blocks_words.js +7 -0
- package/admin/google-blockly/own/field_oid.js +311 -37
- package/admin/i18n/de.json +8 -0
- package/admin/i18n/en.json +8 -0
- package/admin/i18n/es.json +8 -0
- package/admin/i18n/flat.txt +427 -0
- package/admin/i18n/fr.json +8 -0
- package/admin/i18n/it.json +8 -0
- package/admin/i18n/nl.json +8 -0
- package/admin/i18n/pl.json +8 -0
- package/admin/i18n/pt.json +8 -0
- package/admin/i18n/ru.json +8 -0
- package/admin/i18n/uk.json +8 -0
- package/admin/i18n/zh-cn.json +8 -0
- package/admin/img/anthropic.svg +1 -0
- package/admin/img/custom.svg +1 -0
- package/admin/img/deepseek.svg +1 -0
- package/admin/img/gemini.svg +1 -0
- package/admin/img/openai.svg +1 -0
- package/admin/jsonConfig.json +76 -14
- package/admin/mf-manifest.json +1 -1
- package/admin/remoteEntry.js +1 -1
- package/admin/tab.html +6 -6
- package/build/lib/debugger.js +2 -2
- package/build/lib/debugger.js.map +1 -1
- package/build/lib/inspect.js.map +1 -1
- package/build/lib/nodeModulesManagement.js +2 -2
- package/build/lib/nodeModulesManagement.js.map +1 -1
- package/build/lib/protectFs.js +5 -0
- package/build/lib/protectFs.js.map +1 -1
- package/build/lib/sandbox.js +2 -2
- package/build/lib/sandbox.js.map +1 -1
- package/build/main.js +72 -17
- package/build/main.js.map +1 -1
- package/build/types.d.ts +2 -0
- package/docs/de/README.md +21 -8
- package/docs/de/blockly.md +34 -0
- package/docs/en/README.md +21 -8
- package/docs/en/blockly.md +34 -0
- package/install/installTypings.js +1 -1
- package/io-package.json +15 -54
- package/package.json +7 -6
- package/admin/assets/OpenAiDialog-rhLuRLIM.js +0 -13
- package/admin/assets/ScriptEditorVanillaMonaco-DSYvOslZ.js +0 -1
- package/admin/assets/docs-BrInh2Pn.js +0 -2036
- package/admin/assets/index-C49cpVll.js +0 -5
- package/admin/assets/index-XSrHkgLE.js +0 -1230
- package/admin/assets/index-gIA8x-8f.js +0 -1
- package/admin/assets/index-q6iFaoFb.js +0 -986
- package/admin/assets/inheritsLoose-B0Ba5G9z.js +0 -29
- package/admin/assets/useTheme-hy6f3gra.js +0 -1
- package/admin/custom/assets/index-CYc31Gwg.js +0 -960
package/README.md
CHANGED
|
@@ -26,6 +26,20 @@ Executes Javascript, Typescript Scripts.
|
|
|
26
26
|
<!--
|
|
27
27
|
### **WORK IN PROGRESS**
|
|
28
28
|
-->
|
|
29
|
+
### 9.2.0 (2026-04-11)
|
|
30
|
+
* (Eistee82) AI Chat panel with multi-provider support, tool calling, inline completions, and smart-apply
|
|
31
|
+
* (Eistee82) Fix: prevent duplicate 'Stopping script' log when script is not running
|
|
32
|
+
* (Eistee82) Fix: only restart scripts on the instance that owns them
|
|
33
|
+
* (Eistee82) Added OID display mode toggle for Blockly editor: 4 display modes (Name, Name path, State ID, Full ID) with toolbar dropdown, context menu, optional object icons, and translations in 11 languages
|
|
34
|
+
* (Eistee82) Node 25 compatibility: replaced deprecated rmdirSync with rmSync in build tasks
|
|
35
|
+
* (@GermanBluefox) Added support for plain import/export
|
|
36
|
+
* (@GermanBluefox) Correcting error in configuration
|
|
37
|
+
* (@GermanBluefox) disallow writing into node_modules folder by scripts
|
|
38
|
+
* (@GermanBluefox) Correcting start of the script more than one time if restart is triggered
|
|
39
|
+
* (@GermanBluefox) All delayed writings are stopped by the script stop
|
|
40
|
+
* (@GermanBluefox) Added check if a script has been modified by another user/window
|
|
41
|
+
* (@GermanBluefox) Make the instance number more prominent
|
|
42
|
+
|
|
29
43
|
### 9.1.1 (2026-03-19)
|
|
30
44
|
* (GermanBluefox) Small GUI optimizations
|
|
31
45
|
* Added support for custom OpenAI-compatible API endpoints (e.g. Ollama, LM Studio, Google Gemini, DeepSeek, OpenRouter)
|
|
@@ -48,13 +62,6 @@ Executes Javascript, Typescript Scripts.
|
|
|
48
62
|
* (@GermanBluefox) Corrected the rule editor if the condition is empty
|
|
49
63
|
* (@GermanBluefox) Corrected types for TypeScript
|
|
50
64
|
|
|
51
|
-
### 9.0.10 (2025-07-27)
|
|
52
|
-
* (@klein0r) Added Blockly block to format a numeric value
|
|
53
|
-
* (@GermanBluefox) Fixing some blocks in blockly: cron, time
|
|
54
|
-
* (@GermanBluefox) Added a new block: "unconditional return"
|
|
55
|
-
* (@GermanBluefox) Type definitions for TypeScript were updated
|
|
56
|
-
* (@GermanBluefox) Corrected bug with deleting of sub-folders
|
|
57
|
-
|
|
58
65
|
## License
|
|
59
66
|
The MIT License (MIT)
|
|
60
67
|
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import{c as ge,j as s}from"./createSvgIcon-DYs_tNrE.js";import{j as Q,k as J,b as ne,c as we,l as De}from"./iobroker_javascript__loadShare__react__loadShare__.mjs-CTZOFJS2.js";import{z as P,P as fe,o as he,a0 as Ye,a1 as Xe,i as Le,J as Qe,r as Ze,s as et,u as tt,a2 as $e,c as nt,f as ze,g as Te,a3 as Se,a4 as Be,a5 as st}from"./iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-CV1_X-Lf.js";import{_ as m}from"./iobroker_javascript__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__.mjs-DkBjPSMw.js";import{_ as ot}from"./preload-helper-BDBacUwf.js";import{C as rt,b as it,I as at,R as lt}from"./index-SHs7_wDh.js";import{h as ct,i as Pe,k as dt,l as ut}from"./index-DW5CwIma.js";import{g as mt,c as pt}from"./index-wHNMOf-c.js";import"./iobroker_javascript__loadShare__react__loadShare__.mjs_commonjs-proxy-CE9lvhW8.js";import"./iobroker_javascript__loadShare__prop_mf_2_types__loadShare__.mjs-BCtSFofY.js";import"./virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-BJ03G6Pu.js";import"./iobroker_javascript__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-RQRRZMX5.js";import"./iobroker_javascript__loadShare__react_mf_2_dom__loadShare__.mjs-DeVAS-oa.js";import"./inheritsLoose-CIXm_zPk.js";const Ve=ge(s.jsx("path",{d:"M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4zm-1-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8"}),"AddCircleOutline"),ft=ge(s.jsx("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"),ht=ge(s.jsx("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"),gt=ge(s.jsx("path",{d:"M9.01 14H2v2h7.01v3L13 15l-3.99-4zm5.98-1v-3H22V8h-7.01V5L11 9z"}),"CompareArrows"),yt=ge(s.jsx("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"),xt=ge(s.jsx("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"),bt=ge(s.jsx("path",{d:"M2.01 21 23 12 2.01 3 2 10l15 2-15 2z"}),"Send"),vt=ge(s.jsx("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"),St=ot(()=>import("./docs-compact-CKNGiYh2.js"),[],import.meta.url),kt={openai:"img/openai.svg",anthropic:"img/anthropic.svg",gemini:"img/gemini.svg",deepseek:"img/deepseek.svg",custom:"img/custom.svg"},wt={width:16,height:16,flexShrink:0,opacity:.7},jt={ru:"Russian",en:"English",de:"German",es:"Spanish",fr:"French",it:"Italian",pl:"Polish",nl:"Dutch",pt:"Portuguese",uk:"Ukrainian","zh-cn":"Chinese"};let Ce=null,Ae=null,_e=null,Ie=null;function Ct(){Ce=null,Ae=null,_e=null,Ie=null}async function Me(n,t){var r,i,o,h,d,l;if(Ce)return Ce;const e=Object.keys(t);for(let c=0;c<e.length;c++){const a=await n.getObject(e[c]),g=(((r=a==null?void 0:a.native)==null?void 0:r.gptKey)||"").trim(),y=(((i=a==null?void 0:a.native)==null?void 0:i.claudeKey)||"").trim(),p=(((o=a==null?void 0:a.native)==null?void 0:o.geminiKey)||"").trim(),x=(((h=a==null?void 0:a.native)==null?void 0:h.deepseekKey)||"").trim(),v=(((d=a==null?void 0:a.native)==null?void 0:d.gptBaseUrl)||"").trim()||void 0,C=(((l=a==null?void 0:a.native)==null?void 0:l.gptBaseUrlKey)||"").trim()||void 0;if(g||y||p||x||v)return Ce={gptKey:g,claudeKey:y,geminiKey:p,deepseekKey:x,gptBaseUrl:v,gptBaseUrlKey:C},Ce}return null}const _t=["embedding","moderation","dall-e","tts-","whisper","babbage","davinci","sora","omni-moderation"];function It(n){const t=n.toLowerCase();return!_t.some(e=>t.includes(e)||t.startsWith(e))}async function Ot(n,t){const e=await Me(n,t);if(!e)return{models:[],providerMap:{},errors:["No API keys configured"]};const r=Object.keys(t)[0];if(!r)return{models:[],providerMap:{},errors:[m.I18n.t("No running javascript instance found")]};const i=[],o={},h=[],d=(a,g)=>{for(const y of a)It(y)&&(o[y]||(i.push(y),o[y]=g))},l=[],c=(a,g,y,p)=>{l.push(n.sendTo(r,"testApiConnection",{apiKey:g,...y?{baseUrl:y}:{},provider:a==="custom"?"openai":a}).then(x=>{x.models?d(x.models,a):x.error&&h.push(`${p||a}: ${x.error}`)}).catch(x=>{h.push(`${p||a}: ${String(x)}`)}))};return e.gptKey&&c("openai",e.gptKey,void 0,"OpenAI"),e.gptBaseUrl&&c("custom",e.gptBaseUrlKey||"",e.gptBaseUrl,"Custom"),e.claudeKey&&c("anthropic",e.claudeKey,void 0,"Anthropic"),e.geminiKey&&c("gemini",e.geminiKey,void 0,"Gemini"),e.deepseekKey&&c("deepseek",e.deepseekKey,void 0,"DeepSeek"),await Promise.all(l),i.sort(),{models:i,providerMap:o,errors:h}}function Ue(n,t){switch(t){case"anthropic":return{apiKey:n.claudeKey,baseUrl:""};case"gemini":return{apiKey:n.geminiKey,baseUrl:""};case"deepseek":return{apiKey:n.deepseekKey,baseUrl:""};case"custom":return{apiKey:n.gptBaseUrlKey||"",baseUrl:n.gptBaseUrl||""};default:return{apiKey:n.gptKey,baseUrl:""}}}async function Ee(n,t,e){var i;return await n.sendTo(t,"chatCompletion",{timeout:e.timeout||6e5,apiKey:e.apiKey,baseUrl:e.baseUrl||"",model:e.model,provider:e.provider,messages:e.messages,...(i=e.tools)!=null&&i.length?{tools:e.tools}:{}})}async function Fe(n){if(Ie)return Ie;const t=await n.getObjectViewSystem("state","","香"),e=await n.getObjectViewSystem("channel","","香"),r=await n.getObjectViewSystem("device","","香"),i=await n.getObjectViewSystem("folder","","香"),o=await n.getObjectViewSystem("enum","","香");return Ie=Object.assign(t,e,r,i,o),Ie}async function Ge(n){return Fe(n)}function ve(n,t){return n&&typeof n=="object"?n[t]||n.en:n||""}async function Ke(n){var x,v,C,_;if(Ae)return Ae;const t=m.I18n.getLanguage(),e=await Fe(n),r=Object.keys(e).sort(),i=new rt,o=[],h=["UNREACH_STICKY"],d=[it.Types.info],l=[],c=[],a=[],g=[];r.forEach(b=>{var S,T,w;((S=e[b])==null?void 0:S.type)==="enum"?l.push(b):(w=(T=e[b])==null?void 0:T.common)!=null&&w.smartName&&g.push(b)}),l.forEach(b=>{b.startsWith("enum.rooms.")?c.push(b):b.startsWith("enum.functions.")&&a.push(b);const S=e[b].common.members;S!=null&&S.length&&S.forEach(T=>{e[T]&&!g.includes(T)&&g.push(T)})});const y={id:"",objects:e,_keysOptional:r,_usedIdsOptional:o,ignoreIndicators:h,excludedTypes:d},p=[];g.forEach(b=>{y.id=b;const S=i.detect(y);S&&S.forEach(T=>{var X;const w=(X=T.states.find(I=>I.id))==null?void 0:X.id;if(!w||p.find(I=>I.id===w))return;const N=e[w],q={id:w,name:ve(N.common.name,t),type:N.type,deviceType:T.type,states:T.states.filter(I=>I.id).map(I=>({id:I.id,name:I.name,role:I.defaultRole,type:e[I.id].common.type,unit:e[I.id].common.unit,read:e[I.id].common.read??!0,write:e[I.id].common.write??!0}))},$=w.split(".");let U,F;(N.type==="channel"||N.type==="state")&&($.pop(),U=$.join("."),e[U]&&(e[U].type==="channel"||e[U].type==="folder")?($.pop(),F=$.join("."),(!e[F]||e[F].type!=="device"&&e[U].type!=="folder")&&(F=void 0)):U=void 0);const H=c.find(I=>{var se,E,u;return(se=e[I].common.members)!=null&&se.includes(w)||U&&((E=e[I].common.members)!=null&&E.includes(U))?!0:F&&((u=e[I].common.members)==null?void 0:u.includes(F))});H&&(q.room=ve(e[H].common.name,t));const Y=a.find(I=>{var se,E,u;return(se=e[I].common.members)!=null&&se.includes(w)||U&&((E=e[I].common.members)!=null&&E.includes(U))?!0:F&&((u=e[I].common.members)==null?void 0:u.includes(F))});Y&&(q.function=ve(e[Y].common.name,t)),p.push(q)})});for(let b=0;b<p.length;b++){const S=p[b];if(S.type==="state"||S.type==="channel"){const T=S.id.split(".");T.pop();const w=e[T.join(".")];if(w&&(w.type==="channel"||w.type==="device"||w.type==="folder")){S.name=ve(((x=w.common)==null?void 0:x.name)||S.name,t),T.pop();const N=e[T.join(".")];(N==null?void 0:N.type)==="device"&&((v=N.common)!=null&&v.icon)&&(S.name=ve(((C=N.common)==null?void 0:C.name)||S.name,t))}else S.name=ve(((_=w==null?void 0:w.common)==null?void 0:_.name)||S.name,t)}}return Ae=p,p}async function Tt(){return _e||(_e=(await St).default,_e)}function We(){return jt[m.I18n.getLanguage()]||"English"}function Et(n){return`You write ioBroker JavaScript adapter scripts.
|
|
2
|
+
Copy EXACTLY this syntax. Do NOT change the callback signature.
|
|
3
|
+
IMPORTANT: Write all code at top level. NEVER use console.log (use log instead). NEVER define functions with the function keyword.
|
|
4
|
+
|
|
5
|
+
// CORRECT: on() always has ONE callback argument called obj
|
|
6
|
+
on('zigbee.0.sensor.state', (obj) => {
|
|
7
|
+
// obj.state.val = the new value (boolean or number)
|
|
8
|
+
// obj.id = the state ID that changed
|
|
9
|
+
setState('zigbee.0.lamp.state', obj.state.val);
|
|
10
|
+
log('Changed to ' + obj.state.val);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// CORRECT: on() with filter
|
|
14
|
+
on({id: /zigbee\\.0\\..*\\.state$/, change: 'ne'}, (obj) => {
|
|
15
|
+
if (obj.state.val === true) {
|
|
16
|
+
setState('zigbee.0.other.state', true);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Other correct examples:
|
|
21
|
+
setState('id', true);
|
|
22
|
+
setState('id', 50);
|
|
23
|
+
const val = getState('id').val;
|
|
24
|
+
schedule('0 7 * * *', () => { log('runs daily at 07:00'); });
|
|
25
|
+
schedule('0 22 * * *', () => { setState('id', false); });
|
|
26
|
+
|
|
27
|
+
// CORRECT Telegram: always use sendTo, NEVER setState on telegram
|
|
28
|
+
sendTo('telegram.0', 'send', {text: 'Alert: ' + someValue});
|
|
29
|
+
|
|
30
|
+
// CORRECT httpGet: res.data is a STRING, parse JSON with JSON.parse
|
|
31
|
+
httpGet('https://api.example.com/data', (err, res) => {
|
|
32
|
+
const data = JSON.parse(res.data);
|
|
33
|
+
log('Temperature: ' + data.main.temp);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
$('state[state.id=*.state](rooms=Room)').each((id) => { setState(id, false); });
|
|
37
|
+
createState('name', 0, {type: 'number', name: 'Name'});
|
|
38
|
+
// CORRECT: one-time delayed action (turn off after 5 minutes = 300000ms)
|
|
39
|
+
setStateDelayed('zigbee.0.lamp.state', false, false, 5 * 60 * 1000);
|
|
40
|
+
log(formatDate(new Date(), 'DD.MM.YYYY hh:mm'));
|
|
41
|
+
|
|
42
|
+
WRONG: on('id', (id, state) => {}) CORRECT: on('id', (obj) => {})
|
|
43
|
+
WRONG: set('id', true) CORRECT: setState('id', true)
|
|
44
|
+
WRONG: adapter.setState('id', true) CORRECT: setState('id', true)
|
|
45
|
+
WRONG: obj.val or newState.val CORRECT: obj.state.val
|
|
46
|
+
WRONG: on('change', {id: 'x'}, cb) CORRECT: on({id: 'x', change: 'ne'}, cb)
|
|
47
|
+
WRONG: setState('telegram.0', text) CORRECT: sendTo('telegram.0', 'send', {text: text})
|
|
48
|
+
WRONG: res.body.main.temp CORRECT: JSON.parse(res.data).main.temp
|
|
49
|
+
WRONG: function myFunc() {} CORRECT: write code directly, no function definitions
|
|
50
|
+
WRONG: setTimeout(fn, ms) CORRECT: setStateDelayed(id, val, false, ms) for one-time delay
|
|
51
|
+
WRONG: schedule('*/5 * * * *', fn) for one-time delay. schedule() is ONLY for recurring tasks
|
|
52
|
+
Values are boolean (true/false) or numbers, NEVER strings like 'ON'/'OFF'.
|
|
53
|
+
NEVER use: function keyword, require, import, setInterval, setTimeout, console.log, debug().
|
|
54
|
+
|
|
55
|
+
All available functions (use syntax from examples above):
|
|
56
|
+
on(pattern, (obj)=>{}) | once(pattern, (obj)=>{}) | unsubscribe(handler)
|
|
57
|
+
setState(id, val) | getState(id).val | setStateChanged(id, val) | setStateDelayed(id, val, ack, ms) | clearStateDelayed(id)
|
|
58
|
+
existsState(id) | existsObject(id) | getObject(id) | setObject(id, obj) | extendObject(id, obj) | deleteObject(id)
|
|
59
|
+
createState(name, initVal, {type,name,role}) | deleteState(name) | createAlias(name, alias)
|
|
60
|
+
schedule(cron, ()=>{}) | clearSchedule(obj) | scheduleById(id, (obj)=>{}) | getSchedules()
|
|
61
|
+
sendTo(adapter, cmd, msg) | sendToHost(host, cmd, msg)
|
|
62
|
+
$('selector').each((id)=>{}) | $('selector').setState(val) | $('selector').getState()
|
|
63
|
+
log(text) | formatDate(date, 'DD.MM.YYYY hh:mm') | formatTimeDiff(ms) | formatValue(val, decimals)
|
|
64
|
+
getDateObject(str) | getAstroDate(pattern) | isAstroDay() | compareTime(start, end, op)
|
|
65
|
+
exec(cmd, (err,stdout,stderr)=>{}) | httpGet(url, (err,res)=>{}) | httpPost(url, data, (err,res)=>{})
|
|
66
|
+
readFile(adapter, name, (err,data)=>{}) | writeFile(adapter, name, data, cb) | delFile(adapter, name, cb)
|
|
67
|
+
onFile(id, name, withFile, cb) | offFile(id, name) | onStop(cb, timeout)
|
|
68
|
+
getHistory(inst, {id,start,end,aggregate,count}, cb) | getEnums(name) | getIdByName(name)
|
|
69
|
+
wait(ms) | toInt(val) | toFloat(val) | toBoolean(val)
|
|
70
|
+
messageTo(target, data) | onMessage(name, cb) | onLog(severity, cb)
|
|
71
|
+
runScript(name) | startScript(name) | stopScript(name) | isScriptActive(name)
|
|
72
|
+
|
|
73
|
+
Write comments in ${n}. Put code in a \`\`\`javascript code block.`}function Je(n){return`You generate ioBroker Blockly XML blocks. Return Blockly XML in a \`\`\`xml code block.
|
|
74
|
+
Use EXACT state IDs from the plan. Write text/comments in ${n}.
|
|
75
|
+
|
|
76
|
+
IMPORTANT RULES:
|
|
77
|
+
- Return ONLY the inner blocks (no <xml> wrapper needed)
|
|
78
|
+
- Use the exact block types shown below
|
|
79
|
+
- State IDs must be full paths like "zigbee2mqtt.0.0x1234.state"
|
|
80
|
+
- Values are boolean (true/false) or numbers, NEVER strings like "ON"/"OFF"
|
|
81
|
+
- For Telegram use sendto_custom block, NEVER setState on telegram
|
|
82
|
+
|
|
83
|
+
## Block Templates
|
|
84
|
+
|
|
85
|
+
### Trigger: on_ext (react to state changes)
|
|
86
|
+
<block type="on_ext" x="0" y="0">
|
|
87
|
+
<mutation xmlns="http://www.w3.org/1999/xhtml" items="1"></mutation>
|
|
88
|
+
<field name="CONDITION">ne</field>
|
|
89
|
+
<field name="ACK_CONDITION"></field>
|
|
90
|
+
<value name="OID0">
|
|
91
|
+
<shadow type="field_oid"><field name="oid">STATE_ID_HERE</field></shadow>
|
|
92
|
+
</value>
|
|
93
|
+
<statement name="STATEMENT">
|
|
94
|
+
<!-- actions here -->
|
|
95
|
+
</statement>
|
|
96
|
+
</block>
|
|
97
|
+
|
|
98
|
+
### Schedule: schedule (cron-based)
|
|
99
|
+
<block type="schedule" x="0" y="0">
|
|
100
|
+
<field name="SCHEDULE">0 7 * * *</field>
|
|
101
|
+
<statement name="STATEMENT">
|
|
102
|
+
<!-- actions here -->
|
|
103
|
+
</statement>
|
|
104
|
+
</block>
|
|
105
|
+
|
|
106
|
+
### Set State: control
|
|
107
|
+
<block type="control">
|
|
108
|
+
<mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
|
|
109
|
+
<field name="OID">STATE_ID_HERE</field>
|
|
110
|
+
<field name="WITH_DELAY">FALSE</field>
|
|
111
|
+
<value name="VALUE">
|
|
112
|
+
<block type="logic_boolean"><field name="BOOL">TRUE</field></block>
|
|
113
|
+
</value>
|
|
114
|
+
</block>
|
|
115
|
+
|
|
116
|
+
### Get State Value: get_value
|
|
117
|
+
<block type="get_value">
|
|
118
|
+
<field name="ATTR">val</field>
|
|
119
|
+
<field name="OID">STATE_ID_HERE</field>
|
|
120
|
+
</block>
|
|
121
|
+
|
|
122
|
+
### Log: debug
|
|
123
|
+
<block type="debug">
|
|
124
|
+
<field name="Severity">log</field>
|
|
125
|
+
<value name="TEXT">
|
|
126
|
+
<shadow type="text"><field name="TEXT">Message here</field></shadow>
|
|
127
|
+
</value>
|
|
128
|
+
</block>
|
|
129
|
+
|
|
130
|
+
### SendTo (Telegram): sendto_custom
|
|
131
|
+
<block type="sendto_custom">
|
|
132
|
+
<mutation xmlns="http://www.w3.org/1999/xhtml" items="1"></mutation>
|
|
133
|
+
<field name="INSTANCE">telegram.0</field>
|
|
134
|
+
<field name="COMMAND">send</field>
|
|
135
|
+
<field name="LOG"></field>
|
|
136
|
+
<value name="ARG0">
|
|
137
|
+
<block type="text"><field name="TEXT">Message text</field></block>
|
|
138
|
+
</value>
|
|
139
|
+
<value name="ATTR0">
|
|
140
|
+
<block type="text"><field name="TEXT">text</field></block>
|
|
141
|
+
</value>
|
|
142
|
+
</block>
|
|
143
|
+
|
|
144
|
+
### Timeout: timeouts_settimeout
|
|
145
|
+
<block type="timeouts_settimeout">
|
|
146
|
+
<field name="NAME">timeout1</field>
|
|
147
|
+
<field name="DELAY">5000</field>
|
|
148
|
+
<field name="UNIT">ms</field>
|
|
149
|
+
<statement name="STATEMENT">
|
|
150
|
+
<!-- delayed actions -->
|
|
151
|
+
</statement>
|
|
152
|
+
</block>
|
|
153
|
+
|
|
154
|
+
### If/Else: controls_if
|
|
155
|
+
<block type="controls_if">
|
|
156
|
+
<mutation else="1"></mutation>
|
|
157
|
+
<value name="IF0">
|
|
158
|
+
<block type="logic_compare">
|
|
159
|
+
<field name="OP">EQ</field>
|
|
160
|
+
<value name="A"><block type="get_value"><field name="ATTR">val</field><field name="OID">STATE_ID</field></block></value>
|
|
161
|
+
<value name="B"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value>
|
|
162
|
+
</block>
|
|
163
|
+
</value>
|
|
164
|
+
<statement name="DO0"><!-- then --></statement>
|
|
165
|
+
<statement name="ELSE"><!-- else --></statement>
|
|
166
|
+
</block>
|
|
167
|
+
|
|
168
|
+
### Number value
|
|
169
|
+
<block type="math_number"><field name="NUM">0</field></block>
|
|
170
|
+
|
|
171
|
+
### Text value
|
|
172
|
+
<block type="text"><field name="TEXT">hello</field></block>
|
|
173
|
+
|
|
174
|
+
### Boolean value
|
|
175
|
+
<block type="logic_boolean"><field name="BOOL">TRUE</field></block>
|
|
176
|
+
|
|
177
|
+
### Comparison: logic_compare
|
|
178
|
+
<block type="logic_compare">
|
|
179
|
+
<field name="OP">EQ</field>
|
|
180
|
+
<!-- OP can be: EQ, NEQ, LT, LTE, GT, GTE -->
|
|
181
|
+
<value name="A"><!-- left side --></value>
|
|
182
|
+
<value name="B"><!-- right side --></value>
|
|
183
|
+
</block>
|
|
184
|
+
|
|
185
|
+
## Common Patterns
|
|
186
|
+
|
|
187
|
+
### Turn on light when sensor triggers:
|
|
188
|
+
<block type="on_ext" x="0" y="0">
|
|
189
|
+
<mutation xmlns="http://www.w3.org/1999/xhtml" items="1"></mutation>
|
|
190
|
+
<field name="CONDITION">ne</field>
|
|
191
|
+
<field name="ACK_CONDITION"></field>
|
|
192
|
+
<value name="OID0">
|
|
193
|
+
<shadow type="field_oid"><field name="oid">zigbee2mqtt.0.0xSENSOR.occupancy</field></shadow>
|
|
194
|
+
</value>
|
|
195
|
+
<statement name="STATEMENT">
|
|
196
|
+
<block type="controls_if">
|
|
197
|
+
<value name="IF0">
|
|
198
|
+
<block type="logic_compare">
|
|
199
|
+
<field name="OP">EQ</field>
|
|
200
|
+
<value name="A"><block type="get_value"><field name="ATTR">val</field><field name="OID">zigbee2mqtt.0.0xSENSOR.occupancy</field></block></value>
|
|
201
|
+
<value name="B"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value>
|
|
202
|
+
</block>
|
|
203
|
+
</value>
|
|
204
|
+
<statement name="DO0">
|
|
205
|
+
<block type="control">
|
|
206
|
+
<mutation xmlns="http://www.w3.org/1999/xhtml" delay_input="false"></mutation>
|
|
207
|
+
<field name="OID">zigbee2mqtt.0.0xLAMP.state</field>
|
|
208
|
+
<field name="WITH_DELAY">FALSE</field>
|
|
209
|
+
<value name="VALUE"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value>
|
|
210
|
+
</block>
|
|
211
|
+
</statement>
|
|
212
|
+
</block>
|
|
213
|
+
</statement>
|
|
214
|
+
</block>
|
|
215
|
+
|
|
216
|
+
Write comments in ${n}. Put blocks in a \`\`\`xml code block.`}function Re(n){let t=n;return t=t.replace(/<think>[\s\S]*?<\/think>/gi,""),t=t.replace(/<\|endoftext\|>/g,""),t=t.replace(/<\|im_start\|>[\s\S]*?<\|im_end\|>/g,""),t=t.replace(/<\|im_start\|>[\s\S]*/g,""),t.trim()}const Rt=[{type:"function",function:{name:"search_datapoints",description:"Search ioBroker datapoints/states by name or ID pattern. Returns matching object IDs with names, types, roles, and units. Use this to find the correct datapoint ID.",parameters:{type:"object",properties:{query:{type:"string",description:'Search pattern - matches against object ID and name. Examples: "temperature", "carport", "zigbee2mqtt.0.lamp"'},max_results:{type:"number",description:"Maximum number of results to return (default: 20)"}},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 an ioBroker object AND its parent hierarchy. ioBroker objects are organized as: adapter.instance.device.channel.state. This tool returns the object itself plus its parent channel and device if they exist, so you get the full context (e.g. device name, channel grouping). Always use this to understand what a datapoint belongs to.",parameters:{type:"object",properties:{id:{type:"string",description:'The full object ID, e.g. "zigbee2mqtt.0.0x1234.state"'}},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:{}}}}];function Ne(n){return n&&typeof n=="object"?n.en||n.de||"":n||""}async function At(n,t,e=20){const r=await Ge(n),i=t.toLowerCase(),o=[];for(const h of Object.keys(r)){const d=r[h];if(d.type!=="state")continue;const l=d.common,c=Ne(l.name);if((h.toLowerCase().includes(i)||c.toLowerCase().includes(i))&&(o.push({id:h,name:c,type:l.type||"",role:l.role||"",unit:l.unit||""}),o.length>=e))break}return o.length===0?JSON.stringify({message:`No datapoints found matching "${t}"`}):JSON.stringify(o)}async function Mt(n,t){try{const e=await n.getState(t);return JSON.stringify(e?{val:e.val,ts:e.ts?new Date(e.ts).toISOString():null,ack:e.ack,from:e.from}:{error:`State '${t}' not found`})}catch{return JSON.stringify({error:`Failed to read state '${t}'`})}}async function Dt(n,t){var e;try{const r=await n.getObject(t);if(!r)return JSON.stringify({error:`Object '${t}' not found`});const i={id:r._id,type:r.type,common:r.common},o=t.split("."),h=[];for(let d=o.length-1;d>=2;d--){const l=o.slice(0,d).join(".");try{const c=await n.getObject(l);c&&(c.type==="channel"||c.type==="device"||c.type==="folder")&&h.push({id:c._id,type:c.type,name:Ne((e=c.common)==null?void 0:e.name),common:c.common})}catch{}}if(h.length>0&&(i.parents=h),r.type==="channel"||r.type==="device"){const d=await Ge(n),l=[],c=`${t}.`;for(const a of Object.keys(d))if(a.startsWith(c)&&!a.substring(c.length).includes(".")){const y=d[a].common;l.push({id:a,name:Ne(y==null?void 0:y.name),type:(y==null?void 0:y.type)||"",role:(y==null?void 0:y.role)||""})}l.length>0&&(i.children=l)}return JSON.stringify(i)}catch{return JSON.stringify({error:`Failed to read object '${t}'`})}}function qe(n){return ct(n)||n}function Nt(n,t,e=10){const r=t.toLowerCase(),i=[];for(const o of n){const h=o.id.toLowerCase(),d=o.name.toLowerCase(),l=o.id.replace(/^script\.js\./,"").replace(/\./g,"/"),c=o.engineType==="Blockly"||o.engineType==="Rules",a=h.includes(r)||d.includes(r),g=c?qe(o.source):o.source,y=g.toLowerCase().includes(r);if(a||y){const p={id:o.id,path:l,name:o.name,type:c?"Blockly":o.engineType.includes("TypeScript")?"TypeScript":"JavaScript",enabled:o.enabled};if(y){const x=g.split(`
|
|
217
|
+
`),v=[];for(let C=0;C<x.length&&!(x[C].toLowerCase().includes(r)&&(v.push({line:C+1,text:x[C].trim()}),v.length>=5));C++);v.length>0&&(p.matchingLines=v)}if(i.push(p),i.length>=e)break}}return i.length===0?JSON.stringify({message:`No scripts found matching "${t}"`}):JSON.stringify(i)}function Lt(n,t){const e=t.replace(/\//g,".").toLowerCase(),r=n.find(d=>{const l=d.id.toLowerCase();return l===e||l===`script.js.${e}`||l.endsWith(`.${e}`)});if(!r)return JSON.stringify({error:`Script '${t}' not found. Use search_scripts to find available scripts.`});const i=r.engineType==="Blockly"||r.engineType==="Rules",o=i?qe(r.source):r.source,h=r.id.replace(/^script\.js\./,"").replace(/\./g,"/");return JSON.stringify({id:r.id,path:h,name:r.name,type:i?"Blockly":r.engineType.includes("TypeScript")?"TypeScript":"JavaScript",enabled:r.enabled,source:o})}function $t(n){const t=n.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)}async function zt(n,t,e){let r;try{r=JSON.parse(t.function.arguments)}catch{return JSON.stringify({error:`Invalid arguments: ${t.function.arguments}`})}switch(t.function.name){case"search_datapoints":return At(n,r.query,r.max_results||20);case"get_state_value":return Mt(n,r.id);case"get_object_info":return Dt(n,r.id);case"search_scripts":return Nt(e||[],r.query,r.max_results||10);case"read_script":return Lt(e||[],r.id);case"list_scripts":return $t(e||[]);default:return JSON.stringify({error:`Unknown tool: ${t.function.name}`})}}let Bt=0;function je(){return`msg_${Date.now()}_${++Bt}`}function Pt(n){const{socket:t,runningInstances:e,currentCode:r,currentLanguage:i,allScripts:o}=n,[h,d]=Q(()=>{try{const f=window.localStorage.getItem("Editor.aiChatMessages");return f?JSON.parse(f):[]}catch{return[]}}),l=J(f=>{d(M=>{const R=typeof f=="function"?f(M):f,z=R.length>100?R.slice(-100):R;try{window.localStorage.setItem("Editor.aiChatMessages",JSON.stringify(z))}catch{try{const ee=z.slice(-20);window.localStorage.setItem("Editor.aiChatMessages",JSON.stringify(ee))}catch{}}return z})},[]),[c,a]=Q(!1),[g,y]=Q(null),[p,x]=Q(window.localStorage.getItem("Editor.aiChatMode")||"agent"),v=J(f=>{x(f),window.localStorage.setItem("Editor.aiChatMode",f)},[]),[C,_]=Q(null),[b,S]=Q(window.localStorage.getItem("openai-model")||""),[T,w]=Q([]),[N,q]=Q({}),[$,U]=Q(!0),[F,H]=Q(null),Y=ne(null),X=ne(null),I=ne(null),se=J(f=>{S(f),window.localStorage.setItem("openai-model",f)},[]),E=J(async()=>{U(!0),H(null);try{const f=await Ot(t,e);if(w(f.models),q(f.providerMap),f.models.length>0){const M=window.localStorage.getItem("openai-model");M&&f.models.includes(M)?S(M):S(f.models[0])}f.errors.length>0&&H(f.errors.join("; "))}catch(f){H(String(f))}U(!1)},[t,e]);we(()=>{E()},[E]);const u=J(f=>{let M=!1,R=!1;const z=[];let ee=!1;const de=/@([\w/äöüÄÖÜß-]+)/g;let V;for(;(V=de.exec(f))!==null;){const D=V[1].toLowerCase();if(D==="alle"||D==="all")M=!0;else if(D==="geräte"||D==="devices"||D==="geraete")R=!0;else if(ee=!0,o&&o.length>0){const Z=V[1].replace(/\//g,".").toLowerCase(),te=Z.split("."),ue=o.find(ie=>{const ce=ie.id.toLowerCase(),G=ce.replace(/^script\.js\./,"");if(G===Z||G.endsWith(`.${Z}`)||ce===`script.js.${Z}`)return!0;let be=0;for(const me of te){const pe=G.indexOf(me,be);if(pe===-1)return!1;be=pe+me.length}return!0});if(ue)z.push(ue.id);else for(const ie of te){if(ie.length<3)continue;const ce=o.filter(G=>G.id.toLowerCase().includes(`.${ie}`)||G.name.toLowerCase().includes(ie));for(const G of ce)z.includes(G.id)||z.push(G.id)}}}return ee&&z.length===0&&(M=!0),{cleanMessage:f.replace(/@[\w/äöüÄÖÜß]+\s*/g,"").trim(),mentionedScriptIds:z,includeAll:M,includeDevices:R}},[o]),j=J(async(f,M,R)=>{I.current||(I.current=await Tt()),Y.current||(Y.current=await Me(t,e));const z=We(),ee=i==="blockly",de=f||R.length>0;let V=`You are an AI assistant for ioBroker JavaScript adapter scripting. Help the user write, debug, and understand ioBroker scripts. Write comments in ${z}. Use the ioBroker JavaScript API correctly.
|
|
218
|
+
|
|
219
|
+
ioBroker object hierarchy: adapter.instance.device.channel.state
|
|
220
|
+
- A "state" is a single datapoint (e.g. zigbee2mqtt.0.0x1234.temperature)
|
|
221
|
+
- A "channel" groups related states (e.g. zigbee2mqtt.0.0x1234 contains temperature, humidity, battery)
|
|
222
|
+
- A "device" groups channels (e.g. zigbee2mqtt.0.0x1234)
|
|
223
|
+
- The channel/device often has the human-readable name (e.g. "Living Room Sensor")
|
|
224
|
+
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.
|
|
225
|
+
|
|
226
|
+
Available API and syntax rules:
|
|
227
|
+
${I.current}`;if(ee&&(V+="\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."),(M||f)&&(X.current||(X.current=await Ke(t)),V+=`
|
|
228
|
+
|
|
229
|
+
Available smart home devices:
|
|
230
|
+
${JSON.stringify(X.current,null,0)}`),!de&&r)if(ee){const re="%%BLOCKLY_XML%%",D=r.indexOf(re),Z=D!==-1?r.substring(0,D).trim():r,te=D!==-1?r.substring(D+re.length).trim():"";V+=`
|
|
231
|
+
|
|
232
|
+
The user is working on this Blockly script (currently open in the editor).
|
|
233
|
+
|
|
234
|
+
Generated JavaScript (shows the logic):
|
|
235
|
+
\`\`\`javascript
|
|
236
|
+
${Z}
|
|
237
|
+
\`\`\``,te&&(V+=`
|
|
238
|
+
|
|
239
|
+
Blockly XML (use for modifications):
|
|
240
|
+
\`\`\`xml
|
|
241
|
+
${te}
|
|
242
|
+
\`\`\``)}else V+=`
|
|
243
|
+
|
|
244
|
+
The user's question is about this script (currently open in the editor, ${i||"javascript"}):
|
|
245
|
+
\`\`\`${i||"javascript"}
|
|
246
|
+
${r}
|
|
247
|
+
\`\`\``;if(f&&o&&o.length>0)V+=`
|
|
248
|
+
|
|
249
|
+
The 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.
|
|
250
|
+
|
|
251
|
+
${Pe(o,!0)}`;else if(R.length>0&&o){const re=o.filter(D=>R.includes(D.id));re.length>0&&(V+=`
|
|
252
|
+
|
|
253
|
+
IMPORTANT: 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:
|
|
254
|
+
|
|
255
|
+
${Pe(re,!0)}`)}return ee&&(V+=`
|
|
256
|
+
|
|
257
|
+
${Je(z)}`),[{role:"system",content:V}]},[t,e,r,i,o]),k=J(async f=>{if(!f.trim()||c)return;const M=N[b];if(!M){_(m.I18n.t("Please select a valid model"));return}const R=Y.current||await Me(t,e);if(Y.current=R,!R){_(m.I18n.t("No API keys configured"));return}const z=Object.keys(e)[0];if(!z){_(m.I18n.t("No running javascript instance found"));return}const{apiKey:ee,baseUrl:de}=Ue(R,M),V={id:je(),role:"user",content:f,timestamp:Date.now()},re={id:je(),role:"assistant",content:`⏳ ${m.I18n.t("Generating plan...")}`,timestamp:Date.now()};l(D=>[...D,V,re]),a(!0),_(null);try{const D=We();X.current||(X.current=await Ke(t));const Z=X.current||[],te=`Devices in my smart home:
|
|
258
|
+
${JSON.stringify(Z)}
|
|
259
|
+
|
|
260
|
+
I need a plan for this task: ${f}
|
|
261
|
+
|
|
262
|
+
Answer with max 6 lines. Use FULL device IDs from the list above (e.g. zigbee2mqtt.0.0xa4c1383f5ef5fb07.state). No explanation. No reasoning.
|
|
263
|
+
1. IDs: <full IDs from the device list. If a device is not in the list, use TODO_DEVICE_ID as placeholder>
|
|
264
|
+
2. Trigger: <on(id) for state changes OR schedule('min hour * * *') for time-based tasks>
|
|
265
|
+
3. Condition: <when to act>
|
|
266
|
+
4. Actions: <what to set, with full IDs and values. For Telegram use sendTo('telegram.0', 'send', {text: msg})>
|
|
267
|
+
5. Else: <alternative actions or nothing>
|
|
268
|
+
6. Extra: <logging, formatting, etc.>
|
|
269
|
+
Values are boolean (true/false) or numbers, not strings. Use .state not .state_toggle.`,ue=await Ee(t,z,{messages:[{role:"user",content:te}],model:b,provider:M,apiKey:ee,baseUrl:de});if(ue.error){_(ue.error),l(L=>L.slice(0,-2)),a(!1);return}const ie=Re(ue.content||"");l(L=>{const O=[...L],K=O[O.length-1];return(K==null?void 0:K.role)==="assistant"&&(O[O.length-1]={...K,content:`📋 **${m.I18n.t("Plan")}:**
|
|
270
|
+
${ie}`}),O});const ce={id:je(),role:"assistant",content:`⏳ ${m.I18n.t("Generating code...")}`,timestamp:Date.now()};l(L=>[...L,ce]);const G=i==="blockly",be=G?`TASK: ${f}
|
|
271
|
+
|
|
272
|
+
PLAN:
|
|
273
|
+
${ie}
|
|
274
|
+
|
|
275
|
+
Generate 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 ${D}. Put the blocks in a \`\`\`xml code block. You may add a short explanation before or after the XML.`:`TASK: ${f}
|
|
276
|
+
|
|
277
|
+
PLAN:
|
|
278
|
+
${ie}
|
|
279
|
+
|
|
280
|
+
Write 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 ${D}. Put the code in a \`\`\`javascript code block. You may add a short explanation before or after the code.`,me=G?Je(D):Et(D),pe=await Ee(t,z,{messages:[{role:"system",content:me},{role:"user",content:be}],model:b,provider:M,apiKey:ee,baseUrl:de});if(pe.error){_(pe.error),l(L=>L.slice(0,-1)),a(!1);return}const B=Re(pe.content||"");l(L=>{const O=[...L],K=O[O.length-1];return(K==null?void 0:K.role)==="assistant"&&(O[O.length-1]={...K,content:B}),O}),y(`${m.I18n.t("devices")}: ${Z.length}`)}catch(D){_(String(D)),l(Z=>Z.slice(0,-1))}a(!1)},[b,N,c,t,e,i]),oe=J(async f=>{if(p==="code")return k(f);if(!f.trim()||c)return;const M=N[b];if(!M){_(m.I18n.t("Please select a valid model"));return}const R=Y.current||await Me(t,e);if(Y.current=R,!R){_(m.I18n.t("No API keys configured"));return}const z=Object.keys(e)[0];if(!z){_(m.I18n.t("No running javascript instance found"));return}const ee={id:je(),role:"user",content:f,timestamp:Date.now()},de={id:je(),role:"assistant",content:"",timestamp:Date.now()};l(B=>[...B,ee,de]),a(!0),_(null);const{cleanMessage:V,mentionedScriptIds:re,includeAll:D,includeDevices:Z}=u(f),te=[];if(D)te.push(`${m.I18n.t("all scripts")} (${(o==null?void 0:o.length)||0})`);else if(re.length>0){const B=re.map(L=>L.replace(/^script\.js\./,""));te.push(B.join(", "))}else te.push(m.I18n.t("current script"));Z&&te.push(m.I18n.t("devices")),y(`${m.I18n.t("Context")}: ${te.join(" + ")}`);const ue=await j(D,Z,re),{apiKey:ie,baseUrl:ce}=Ue(R,M);let G=V||f;if(o&&o.length>0){const B=G.match(/\b[\w-]+\.\d+\.[\w.-]+/g);if(B){const L=[];for(const O of new Set(B)){const K=dt(o,O);K.length>0&&L.push(`Datapoint "${O}" is used in:
|
|
281
|
+
${K.map(xe=>` - ${xe.scriptName} (${xe.scriptId}) line ${xe.lineNumber}: ${xe.usageType} → ${xe.line}`).join(`
|
|
282
|
+
`)}`)}L.length>0&&(G+=`
|
|
283
|
+
|
|
284
|
+
[Automatic analysis results]
|
|
285
|
+
${L.join(`
|
|
286
|
+
|
|
287
|
+
`)}`)}}const be=[...ue,...h.filter(B=>B.role!=="system").map(B=>({role:B.role,content:B.content})),{role:"user",content:G}],me=p==="agent"&&M!=="anthropic",pe=5;try{const B=[...be];for(let L=0;L<pe;L++){const O=await Ee(t,z,{messages:B,model:b,provider:M,apiKey:ie,baseUrl:ce,...me?{tools:Rt}:{}});if(O.error){if(me&&L===0&&O.error.toLowerCase().includes("tool")){const W=await Ee(t,z,{messages:B,model:b,provider:M,apiKey:ie,baseUrl:ce});if(W.error)_(W.error),l(A=>A.slice(0,-1));else{const A=Re(W.content||"");l(ae=>{const le=[...ae],Oe=le[le.length-1];return(Oe==null?void 0:Oe.role)==="assistant"&&(le[le.length-1]={...Oe,content:A}),le})}break}_(O.error),l(W=>W.slice(0,-1));break}let K=O.tool_calls;if((!K||K.length===0)&&me&&O.content){const W=O.content.trim();try{const A=JSON.parse(W);A.name&&A.arguments&&(K=[{id:`text_tool_${Date.now()}`,type:"function",function:{name:A.name,arguments:JSON.stringify(A.arguments)}}])}catch{}}if(!K||K.length===0){const W=Re(O.content||"");l(A=>{const ae=[...A],le=ae[ae.length-1];return(le==null?void 0:le.role)==="assistant"&&(ae[ae.length-1]={...le,content:W}),ae});break}O.tool_calls=K;const xe=O.tool_calls.map(W=>{let A={};try{A=JSON.parse(W.function.arguments)}catch{}switch(W.function.name){case"search_datapoints":return`🔍 ${m.I18n.t("Searching datapoints")}: "${String(A.query||"")}"`;case"get_state_value":return`📊 ${m.I18n.t("Reading value")}: ${String(A.id||"")}`;case"get_object_info":return`📋 ${m.I18n.t("Loading object info")}: ${String(A.id||"")}`;case"search_scripts":return`🔍 ${m.I18n.t("Searching scripts")}: "${String(A.query||"")}"`;case"read_script":return`📖 ${m.I18n.t("Reading script")}: ${String(A.id||"")}`;case"list_scripts":return`📂 ${m.I18n.t("Loading script list")}`;default:return`⚙️ ${W.function.name}`}});l(W=>{const A=[...W],ae=A[A.length-1];return(ae==null?void 0:ae.role)==="assistant"&&(A[A.length-1]={...ae,content:xe.join(`
|
|
288
|
+
`)}),A}),B.push({role:"assistant",content:O.content||"",tool_calls:O.tool_calls});for(const W of O.tool_calls){const A=await zt(t,W,o);B.push({role:"tool",tool_call_id:W.id,content:A})}}}catch(B){_(String(B)),l(L=>L.slice(0,-1))}a(!1)},[b,N,h,c,t,e,j,u,o,p,k]),ye=J(()=>{l([]),_(null),a(!1),y(null),Ct(),window.localStorage.removeItem("Editor.aiChatHistory")},[l]);return{messages:h,isLoading:c,error:C,model:b,availableModels:T,modelProviderMap:N,modelsLoading:$,modelsError:F,lastContextInfo:g,mode:p,setMode:v,setModel:se,sendMessage:oe,clearChat:ye,retryLoadModels:E}}const Ut=({code:n,language:t,themeType:e,onInsertCode:r,onShowDiff:i})=>{const o=ne(null);we(()=>{var c;const d=window.monaco;if(!o.current||!((c=d==null?void 0:d.editor)!=null&&c.colorize))return;const l=t==="ts"||t==="typescript"?"typescript":t||"javascript";d.editor.colorize(n,l,{theme:e==="dark"?"vs-dark":"vs"}).then(a=>{o.current&&(o.current.innerHTML=a)})},[n,t,e]);const h=J(()=>{navigator.clipboard.writeText(n)},[n]);return s.jsxs(P,{sx:{position:"relative",my:1,borderRadius:1,overflow:"hidden",border:"1px solid",borderColor:"divider"},children:[s.jsxs(P,{sx:{display:"flex",justifyContent:"space-between",alignItems:"center",px:1,py:.5,bgcolor:"action.hover",borderBottom:"1px solid",borderColor:"divider"},children:[s.jsx(P,{sx:{fontSize:"0.75rem",color:"text.secondary",textTransform:"uppercase"},children:t||"javascript"}),s.jsxs(P,{children:[s.jsx(fe,{title:m.I18n.t("Copy"),children:s.jsx(he,{size:"small",onClick:h,children:s.jsx(mt,{sx:{fontSize:16}})})}),r&&s.jsx(fe,{title:m.I18n.t("Insert into editor"),children:s.jsx(he,{size:"small",onClick:()=>r(n),children:s.jsx(Ve,{sx:{fontSize:16}})})}),i&&s.jsx(fe,{title:m.I18n.t("Show as diff"),children:s.jsx(he,{size:"small",onClick:()=>i(n),children:s.jsx(gt,{sx:{fontSize:16}})})})]})]}),s.jsx("pre",{ref:o,style:{margin:0,padding:"8px 12px",overflow:"auto",maxHeight:400,fontSize:"13px",fontFamily:"'Cascadia Code', 'Fira Code', 'Consolas', monospace",backgroundColor:e==="dark"?"#1e1e1e":"#f8f8f8",color:e==="dark"?"#d4d4d4":"#333"},children:n})]})},Kt=({xml:n,themeType:t})=>{const e=ne(null),r=ne(null),[i,o]=Q(60),h=ne(!1);return we(()=>{h.current&&(h.current=!1,requestAnimationFrame(()=>{const d=window.Blockly,l=r.current;d&&l&&(d.svgResize(l),l.scrollCenter())}))},[i]),we(()=>{const d=window.Blockly;if(!(!d||!e.current)){r.current&&(r.current.dispose(),r.current=null);try{const l=d.inject(e.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:t==="dark"?ut:"classic",media:"google-blockly/media/"});r.current=l;let c=n.trim();c.startsWith("<xml")||(c=`<xml xmlns="https://developers.google.com/blockly/xml">${c}</xml>`);const a=d.utils.xml.textToDom(c);let g=10;const y=Array.from(a.querySelectorAll(":scope > block"));for(const v of y)v.setAttribute("x","10"),v.setAttribute("y",String(g)),g+=200;d.Xml.domToWorkspace(a,l);const p=l.getTopBlocks(!1);if(p.length>1){let v=10;for(const C of p){const _=C.getRelativeToSurfaceXY();C.moveBy(10-_.x,v-_.y),v+=C.getHeightWidth().height+20}}const x=l.getBlocksBoundingBox();if(x){const v=x.bottom-x.top+20,C=Math.max(60,Math.ceil(v));h.current=!0,o(C)}}catch{}return()=>{r.current&&(r.current.dispose(),r.current=null)}}},[n,t]),s.jsx(P,{ref:e,sx:{width:"100%",height:i,minHeight:60,borderRadius:1,overflow:"hidden",border:"1px solid",borderColor:"divider"}})};function Wt(n){const t=[],e=/```(\w*)\n?([\s\S]*?)```/g;let r=0,i;for(;(i=e.exec(n))!==null;){if(i.index>r){const o=n.substring(r,i.index).trim();o&&t.push({type:"text",content:o})}t.push({type:"code",content:i[2].trim(),language:i[1]||"javascript"}),r=i.index+i[0].length}if(r<n.length){const o=n.substring(r).trim();o&&t.push({type:"text",content:o})}return t.length===0&&t.push({type:"text",content:n}),t}function ke(n){const t=[],e=/(\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`)/g;let r=0,i,o=0;for(;(i=e.exec(n))!==null;)i.index>r&&t.push(n.substring(r,i.index)),i[2]?t.push(s.jsx("strong",{children:i[2]},o++)):i[3]?t.push(s.jsx("em",{children:i[3]},o++)):i[4]&&t.push(s.jsx("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]},o++)),r=i.index+i[0].length;return r<n.length&&t.push(n.substring(r)),t}function He(n){return n.trim().startsWith("|")&&n.trim().endsWith("|")}function Jt(n){return/^\|[\s:]*-+[\s:|-]*\|$/.test(n.trim())}function Ht(n,t,e){const r=t.palette.mode==="dark",i=d=>d.trim().replace(/^\||\|$/g,"").split("|").map(l=>l.trim()),o=i(n[0]),h=n.slice(2).map(i);return s.jsx(P,{sx:{overflowX:"auto",my:1},children:s.jsxs("table",{style:{borderCollapse:"collapse",width:"100%",fontSize:"0.8rem",color:t.palette.text.primary},children:[s.jsx("thead",{children:s.jsx("tr",{children:o.map((d,l)=>s.jsx("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:ke(d)},l))})}),s.jsx("tbody",{children:h.map((d,l)=>s.jsx("tr",{style:{backgroundColor:l%2===1?r?t.palette.grey[900]:t.palette.grey[50]:void 0},children:d.map((c,a)=>s.jsx("td",{style:{border:`1px solid ${t.palette.divider}`,padding:"6px 10px",color:t.palette.text.primary},children:ke(c)},a))},l))})]})},e)}function Vt(n,t){const e=n.split(`
|
|
289
|
+
`),r=[];let i=0,o=0;for(;o<e.length;){const d=e[o].trim();if(d===""){o++;continue}if(/^(-{3,}|\*{3,}|_{3,})$/.test(d)){r.push(s.jsx("hr",{style:{border:"none",borderTop:`1px solid ${t.palette.divider}`,margin:"8px 0"}},i++)),o++;continue}const l=d.match(/^(#{1,4})\s+(.+)$/);if(l){const c=l[1].length,a=["1.2em","1.1em","1em","0.95em"];r.push(s.jsx("div",{style:{fontWeight:600,fontSize:a[c-1],margin:"8px 0 4px"},children:ke(l[2])},i++)),o++;continue}if(He(d)&&o+1<e.length&&Jt(e[o+1].trim())&&o+2<e.length){const c=[e[o],e[o+1]];let a=o+2;for(;a<e.length&&He(e[a]);)c.push(e[a]),a++;r.push(Ht(c,t,i++)),o=a;continue}if(/^[-*+]\s/.test(d)){const c=[];for(;o<e.length&&/^\s*[-*+]\s/.test(e[o]);)c.push(e[o].replace(/^\s*[-*+]\s/,"").trim()),o++;r.push(s.jsx("ul",{style:{margin:"4px 0",paddingLeft:20},children:c.map((a,g)=>s.jsx("li",{children:ke(a)},g))},i++));continue}if(/^\d+[.)]\s/.test(d)){const c=[];for(;o<e.length&&/^\s*\d+[.)]\s/.test(e[o]);)c.push(e[o].replace(/^\s*\d+[.)]\s/,"").trim()),o++;r.push(s.jsx("ol",{style:{margin:"4px 0",paddingLeft:20},children:c.map((a,g)=>s.jsx("li",{children:ke(a)},g))},i++));continue}r.push(s.jsx("div",{children:ke(d)},i++)),o++}return r}const Ft=({message:n,themeType:t,currentLanguage:e,onInsertCode:r,onShowDiff:i,onApplyCode:o})=>{const h=n.role==="user",d=Ye(),l=De(()=>Wt(n.content),[n.content]),c=(a,g)=>!!(a==="xml"||a==="blockly"||e==="blockly"&&g&&/<block\s+type=/.test(g));return s.jsxs(P,{sx:{display:"flex",gap:1,px:1.5,py:1,"&:hover":{bgcolor:"action.hover"}},children:[s.jsx(Xe,{sx:{width:28,height:28,bgcolor:h?t==="dark"?"primary.dark":"primary.main":t==="dark"?"secondary.dark":"secondary.main",flexShrink:0,mt:.5},children:h?s.jsx(yt,{sx:{fontSize:18}}):s.jsx(vt,{sx:{fontSize:18}})}),s.jsx(P,{sx:{flex:1,minWidth:0,fontSize:"0.875rem",lineHeight:1.6},children:l.map((a,g)=>a.type==="code"?c(a.language,a.content)?s.jsxs(P,{sx:{my:1},children:[s.jsx(Kt,{xml:a.content,themeType:t}),s.jsxs(P,{sx:{display:"flex",gap:.5,mt:.5},children:[o&&s.jsx(Le,{size:"small",variant:"contained",color:"primary",startIcon:s.jsx(xt,{sx:{fontSize:14}}),onClick:()=>o(a.content),sx:{textTransform:"none",fontSize:"0.75rem"},children:m.I18n.t("Apply blocks")}),r&&s.jsx(Le,{size:"small",variant:"outlined",startIcon:s.jsx(Ve,{sx:{fontSize:14}}),onClick:()=>r(a.content),sx:{textTransform:"none",fontSize:"0.75rem"},children:m.I18n.t("Insert blocks")})]})]},g):s.jsx(Ut,{code:a.content,language:a.language||"javascript",themeType:t,onInsertCode:r,onShowDiff:i},g):s.jsx(P,{sx:{wordBreak:"break-word",color:d.palette.text.primary},children:Vt(a.content,d)},g))})]})};function Gt(){return[{id:"@all",label:m.I18n.t("mention @all"),descriptionKey:"All scripts"},{id:"@devices",label:m.I18n.t("mention @devices"),descriptionKey:"Smart home devices"}]}function qt({provider:n,isDark:t}){return kt[n]?s.jsx("img",{src:`./img/${n}.svg`,alt:n,style:{...wt,...t?{filter:"invert(0.85)"}:{}},onError:r=>{r.target.style.display="none"}}):null}function Yt(){try{const n=window.localStorage.getItem("Editor.aiChatHistory");return n?JSON.parse(n):[]}catch{return[]}}const Xt=({onSend:n,disabled:t,themeType:e,hasSelection:r,selectionText:i,allScripts:o,model:h,availableModels:d,modelProviderMap:l,modelsLoading:c,onModelChange:a,mode:g,onModeChange:y})=>{const[p,x]=Q(""),[v,C]=Q(!1),[_,b]=Q(""),[S,T]=Q(0),w=ne(null),N=ne(-1),q=ne(Yt()),$=ne(-1),U=ne(""),F=De(()=>{const j=Gt().map(k=>({...k,description:m.I18n.t(k.descriptionKey)}));if(o)for(const k of o){const oe=k.id.replace(/^script\.js\./,"").replace(/\./g,"/");j.push({id:`@${oe}`,label:`@${oe}`,description:`${k.name} [${k.enabled?"active":"inactive"}]`})}return j},[o]),H=De(()=>{if(!_)return F;const u=_.toLowerCase();return F.filter(j=>j.id.toLowerCase().includes(u)||j.description.toLowerCase().includes(u))},[F,_]);we(()=>{T(0)},[_]);const Y=J(()=>{const u=p.trim();if(!u||t)return;let j=u;r&&i&&(j=`[Selected code in editor]
|
|
290
|
+
\`\`\`
|
|
291
|
+
${i}
|
|
292
|
+
\`\`\`
|
|
293
|
+
|
|
294
|
+
${u}`),q.current.push(u),$.current=-1,U.current="";try{const k=q.current.slice(-50);window.localStorage.setItem("Editor.aiChatHistory",JSON.stringify(k))}catch{}n(j),x(""),C(!1),requestAnimationFrame(()=>{var k;return(k=w.current)==null?void 0:k.focus()})},[p,t,n,r,i]),X=J(u=>{const j=N.current,k=w.current;if(j<0){const R=p?`${p}${u} `:`${u} `;x(R),C(!1),b(""),setTimeout(()=>{k&&(k.focus(),k.setSelectionRange(R.length,R.length))},0);return}const oe=p.substring(0,j),ye=(k==null?void 0:k.selectionStart)??p.length,f=p.substring(ye),M=`${oe}${u} ${f}`;x(M),C(!1),b(""),N.current=-1,setTimeout(()=>{if(k){const R=oe.length+u.length+1;k.focus(),k.setSelectionRange(R,R)}},0)},[p]),I=J(()=>{N.current=-1,b(""),C(u=>!u)},[]),se=J(u=>{const j=u.target.value;x(j);const k=u.target.selectionStart??j.length,ye=j.substring(0,k).match(/@([\w/äöüÄÖÜß]*)$/);ye?(N.current=k-ye[0].length,b(ye[1]),C(!0)):(C(!1),b(""))},[]),E=J(u=>{if(v&&H.length>0){if(u.key==="ArrowDown"){u.preventDefault(),T(j=>(j+1)%H.length);return}if(u.key==="ArrowUp"){u.preventDefault(),T(j=>(j-1+H.length)%H.length);return}if(u.key==="Enter"||u.key==="Tab"){u.preventDefault(),X(H[S].id);return}if(u.key==="Escape"){u.preventDefault(),C(!1);return}}if(u.key==="ArrowUp"&&!v&&q.current.length>0){const j=w.current,k=!j||j.selectionStart===0,oe=!p.includes(`
|
|
295
|
+
`);if(k&&oe){u.preventDefault(),$.current===-1?(U.current=p,$.current=q.current.length-1):$.current>0&&$.current--,x(q.current[$.current]);return}}if(u.key==="ArrowDown"&&!v&&$.current>=0){const j=w.current,k=!j||j.selectionStart===p.length,oe=!p.includes(`
|
|
296
|
+
`);if(k&&oe){u.preventDefault(),$.current<q.current.length-1?($.current++,x(q.current[$.current])):($.current=-1,x(U.current));return}}u.key==="Enter"&&!u.shiftKey&&(u.preventDefault(),Y())},[Y,v,H,S,X,p]);return s.jsxs(P,{sx:{borderTop:"1px solid",borderColor:"divider",position:"relative"},children:[v&&H.length>0&&s.jsx(Qe,{elevation:4,sx:{position:"absolute",bottom:"100%",left:8,right:8,maxHeight:200,overflow:"auto",zIndex:10,mb:.5},children:s.jsx(Ze,{dense:!0,disablePadding:!0,children:H.slice(0,15).map((u,j)=>s.jsx(et,{selected:j===S,onClick:()=>X(u.id),sx:{py:.25,minHeight:32},children:s.jsx(tt,{primary:u.label,secondary:u.description,primaryTypographyProps:{fontSize:"0.8rem",fontWeight:500},secondaryTypographyProps:{fontSize:"0.7rem"}})},u.id))})}),g==="code"&&s.jsx($e,{label:`${m.I18n.t("mention @devices")} — ${m.I18n.t("Smart home devices")}`,size:"small",variant:"outlined",sx:{mx:1,mt:.5,maxWidth:"calc(100% - 16px)"}}),r&&i&&s.jsx($e,{icon:s.jsx(at,{sx:{fontSize:14}}),label:m.I18n.t("Selected code as context"),size:"small",variant:"outlined",sx:{mx:1,mt:.5,maxWidth:"calc(100% - 16px)"}}),s.jsxs(P,{sx:{mx:1,mt:.5,mb:.5,border:"1px solid",borderColor:"divider",borderRadius:1.5,overflow:"hidden","&:focus-within":{borderColor:"primary.main"}},children:[s.jsx(nt,{inputRef:w,fullWidth:!0,multiline:!0,maxRows:6,placeholder:m.I18n.t("Ask about your script..."),value:p,onChange:se,onKeyDown:E,disabled:t,onBlur:()=>{setTimeout(()=>C(!1),200)},variant:"standard",slotProps:{input:{disableUnderline:!0}},sx:{px:1.5,pt:1,pb:.5,"& .MuiInputBase-root":{fontSize:"0.875rem"}}}),s.jsxs(P,{sx:{display:"flex",alignItems:"center",gap:.75,px:1,pb:.5},children:[s.jsx(fe,{title:m.I18n.t("Mode: Chat = conversation only, Agent = can read/analyze scripts, Code = can read and modify scripts"),enterDelay:500,children:s.jsxs(ze,{value:g,onChange:u=>y(u.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:[s.jsx(Te,{value:"chat",sx:{fontSize:"0.75rem"},children:"💬 Chat"}),s.jsx(Te,{value:"agent",sx:{fontSize:"0.75rem"},children:"🤖 Agent"}),s.jsx(Te,{value:"code",sx:{fontSize:"0.75rem"},children:"💻 Code"})]})}),s.jsx(ze,{value:h,onChange:u=>a(u.target.value),size:"small",disabled:c||d.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:d.map(u=>s.jsxs(Te,{value:u,sx:{fontSize:"0.75rem",display:"flex",gap:.5},children:[s.jsx(qt,{provider:l[u],isDark:e==="dark"}),u]},u))}),s.jsx(fe,{title:m.I18n.t("Mention scripts as context for the AI. Use @all for all scripts or @scriptName for a specific one."),enterDelay:500,children:s.jsx(he,{size:"small",onClick:I,sx:{p:"3px",color:v?"primary.main":"text.secondary",border:"1px solid",borderColor:v?"primary.main":"text.secondary",bgcolor:v?void 0:"action.hover",borderRadius:3,"&:hover":{borderColor:"text.disabled",bgcolor:"action.hover"}},children:s.jsx(ht,{sx:{fontSize:16}})})}),s.jsx(P,{sx:{flex:1}}),s.jsxs(Se,{variant:"caption",sx:{color:"text.disabled",fontSize:"0.65rem",mr:.5,whiteSpace:"nowrap"},children:["Enter ",m.I18n.t("to send")]}),s.jsx(fe,{title:`${m.I18n.t("Send")} (Enter)`,children:s.jsx("span",{children:s.jsx(he,{color:"primary",onClick:Y,disabled:t||!p.trim(),size:"small",sx:{p:.25},children:s.jsx(bt,{sx:{fontSize:18}})})})})]})]})]})},pn=({socket:n,runningInstances:t,themeType:e,currentCode:r,currentLanguage:i,selectedCode:o,allScripts:h,onInsertCode:d,onShowDiff:l,onApplyCode:c,onClose:a})=>{var se;const g=ne(null),y=De(()=>({socket:n,runningInstances:t,currentCode:r,currentLanguage:i,allScripts:h}),[n,t,r,i,h]),{messages:p,isLoading:x,error:v,model:C,availableModels:_,modelProviderMap:b,modelsLoading:S,modelsError:T,lastContextInfo:w,mode:N,setMode:q,setModel:$,sendMessage:U,clearChat:F,retryLoadModels:H}=Pt(y);we(()=>{var E;(E=g.current)==null||E.scrollIntoView({behavior:"smooth"})},[p]);const Y=J(E=>{d==null||d(E)},[d]),X=J(E=>{l==null||l(E)},[l]),I=J(E=>{c==null||c(E)},[c]);return s.jsxs(P,{sx:{display:"flex",flexDirection:"column",height:"100%",bgcolor:"background.default","& .ai-chat-inline-code":{backgroundColor:"action.selected",color:"text.primary",border:"1px solid",borderColor:"divider"}},children:[s.jsxs(P,{sx:{display:"flex",alignItems:"center",gap:1,px:1,py:.5,borderBottom:"1px solid",borderColor:"divider",bgcolor:e==="dark"?"grey.900":"grey.100",flexShrink:0},children:[s.jsx(Se,{variant:"subtitle2",sx:{fontWeight:600,flex:1,color:"text.primary"},children:m.I18n.t("AI Chat")}),S&&s.jsx(Be,{size:16}),s.jsx(fe,{title:m.I18n.t("New chat"),children:s.jsx(he,{size:"small",onClick:F,children:s.jsx(ft,{sx:{fontSize:18}})})}),s.jsx(fe,{title:m.I18n.t("Close"),children:s.jsx(he,{size:"small",onClick:a,children:s.jsx(pt,{sx:{fontSize:18}})})})]}),(v||T)&&s.jsx(st,{severity:"error",sx:{m:1,py:0},action:T?s.jsx(he,{size:"small",onClick:H,children:s.jsx(lt,{sx:{fontSize:16}})}):void 0,children:v||T}),w&&s.jsx(Se,{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:w}),s.jsxs(P,{sx:{flex:1,overflow:"auto",py:1},children:[p.length===0&&!x&&s.jsxs(P,{sx:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",color:"text.secondary",px:3,textAlign:"center"},children:[s.jsx(Se,{variant:"body2",sx:{mb:1},children:m.I18n.t("Ask questions about your script, request changes, or generate new code.")}),s.jsxs(Se,{variant:"caption",color:"text.disabled",children:["Enter ",m.I18n.t("to send"),", Shift+Enter ",m.I18n.t("for new line")]})]}),p.filter(E=>E.role!=="system").map(E=>s.jsx(Ft,{message:E,themeType:e,currentLanguage:i,onInsertCode:Y,onShowDiff:X,onApplyCode:I},E.id)),x&&((se=p[p.length-1])==null?void 0:se.content)===""&&s.jsxs(P,{sx:{display:"flex",alignItems:"center",gap:1,px:2,py:1},children:[s.jsx(Be,{size:16}),s.jsx(Se,{variant:"caption",color:"text.secondary",children:m.I18n.t("Thinking...")})]}),s.jsx("div",{ref:g})]}),s.jsx(Xt,{onSend:U,disabled:x||_.length===0,themeType:e,hasSelection:!!o,selectionText:o,allScripts:h,model:C,availableModels:_,modelProviderMap:b,modelsLoading:S,onModelChange:$,mode:N,onModeChange:q})]})};export{pn as default};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const S=[/getState\s*\(\s*['"`]$/,/setState\s*\(\s*['"`]$/,/setStateChanged\s*\(\s*['"`]$/,/setStateDelayed\s*\(\s*['"`]$/,/existsState\s*\(\s*['"`]$/,/existsObject\s*\(\s*['"`]$/,/getObject\s*\(\s*['"`]$/,/on\s*\(\s*['"`]$/,/once\s*\(\s*['"`]$/,/subscribe\s*\(\s*['"`]$/,/on\s*\(\s*\{\s*id\s*:\s*['"`]$/,/\$\s*\(\s*['"`]$/];let w=null,p=null;function O(n,m){return n&&typeof n=="object"?n[m]||n.en||"":n||""}async function T(n){return w||p||(p=(async()=>{var I;const m=window.systemLang||"en",g=await n.getObjectViewSystem("state","","香"),f=await n.getObjectViewSystem("enum","","香"),$={},h={};for(const o of Object.keys(f)){const r=f[o],t=(I=r.common)==null?void 0:I.members;if(!t)continue;const c=O(r.common.name,m);for(const a of t)o.startsWith("enum.rooms.")?$[a]=c:o.startsWith("enum.functions.")&&(h[a]=c)}const s=[];for(const o of Object.keys(g)){const r=g[o];if(!(r!=null&&r.common))continue;const t=r.common,c=O(t.name,m),a=o.split(".");let u,i;for(let y=a.length;y>=2;y--){const C=a.slice(0,y).join(".");if(!u&&$[C]&&(u=$[C]),!i&&h[C]&&(i=h[C]),u&&i)break}s.push({id:o,name:c,type:t.type,role:t.role,unit:t.unit,room:u,func:i,read:t.read,write:t.write})}return w=s,p=null,s})(),p)}function b(){w=null,p=null}function L(n,m){const g=[];for(const f of["javascript","typescript"]){const $=n.languages.registerCompletionItemProvider(f,{triggerCharacters:["'",'"',"`","."],async provideCompletionItems(h,s){const o=h.getLineContent(s.lineNumber).substring(0,s.column-1);if(!S.some(e=>e.test(o)))return;const t=o.match(/['"`]([^'"`]*)$/);if(!t)return;const c=t[1],a=s.column-c.length,u=await T(m);let i;if(c){const e=c.toLowerCase();i=u.filter(l=>l.id.toLowerCase().includes(e)||l.name.toLowerCase().includes(e))}else i=u;i=i.slice(0,100);const y={startLineNumber:s.lineNumber,startColumn:a,endLineNumber:s.lineNumber,endColumn:s.column};return{suggestions:i.map(e=>{const l=[];e.name&&l.push(e.name),e.room&&l.push(`Room: ${e.room}`),e.func&&l.push(`Function: ${e.func}`);const d=[];return e.role&&d.push(`Role: ${e.role}`),e.type&&d.push(`Type: ${e.type}`),e.unit&&d.push(`Unit: ${e.unit}`),d.push(`Read: ${e.read!==!1?"yes":"no"}`),d.push(`Write: ${e.write!==!1?"yes":"no"}`),{label:e.id,kind:n.languages.CompletionItemKind.Value,detail:l.join(" | "),documentation:d.join(`
|
|
2
|
+
`),insertText:e.id,range:y,filterText:`${e.id} ${e.name}`,sortText:e.id}})}}});g.push($)}return{dispose:()=>{g.forEach(f=>f.dispose())}}}export{b as clearDatapointCache,L as registerDatapointProvider};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e}from"./createSvgIcon-DYs_tNrE.js";import{b as a,c as I,k as b}from"./iobroker_javascript__loadShare__react__loadShare__.mjs-CTZOFJS2.js";import{z as x,F as k,a3 as v,i as p}from"./iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-CV1_X-Lf.js";import{_ as c}from"./iobroker_javascript__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__.mjs-DkBjPSMw.js";import{I as g,c as M}from"./index-wHNMOf-c.js";import"./iobroker_javascript__loadShare__react__loadShare__.mjs_commonjs-proxy-CE9lvhW8.js";import"./iobroker_javascript__loadShare__prop_mf_2_types__loadShare__.mjs-BCtSFofY.js";const D=({originalCode:d,modifiedCode:t,language:s,themeType:f,onAccept:m,onReject:h})=>{const i=a(null),u=a(null),n=a(null);I(()=>{const r=window.monaco;if(!r||!i.current)return;const o=r.editor.createDiffEditor(i.current,{readOnly:!1,originalEditable:!1,renderSideBySide:!0,automaticLayout:!0,theme:f==="dark"?"vs-dark":"vs",scrollBeyondLastLine:!1,minimap:{enabled:!1}}),_=r.editor.createModel(d,s),l=r.editor.createModel(t,s);return n.current=l,o.setModel({original:_,modified:l}),u.current=o,()=>{o.dispose(),_.dispose(),l.dispose(),u.current=null,n.current=null}},[d,t,s,f]);const j=b(()=>{var o;const r=((o=n.current)==null?void 0:o.getValue())||t;m(r)},[t,m]);return e.jsxs(x,{sx:{display:"flex",flexDirection:"column",height:"100%",width:"100%"},children:[e.jsxs(k,{variant:"dense",sx:{minHeight:36,bgcolor:"background.paper",borderBottom:"1px solid",borderColor:"divider",gap:1,flexShrink:0},children:[e.jsx(v,{variant:"subtitle2",sx:{flex:1},children:c.I18n.t("AI suggested changes")}),e.jsx(p,{variant:"contained",color:"success",size:"small",startIcon:e.jsx(g,{}),onClick:j,children:c.I18n.t("Accept")}),e.jsx(p,{variant:"outlined",color:"error",size:"small",startIcon:e.jsx(M,{}),onClick:h,children:c.I18n.t("Reject")})]}),e.jsx(x,{ref:i,sx:{flex:1,overflow:"hidden"}})]})};export{D as default};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
const M=`You are a code completion engine for ioBroker JavaScript adapter scripts.
|
|
2
|
+
Complete the code at the cursor position marked with <CURSOR>.
|
|
3
|
+
Return ONLY the completion text, no explanation, no markdown fences, no comments about what you did.
|
|
4
|
+
If you cannot complete, return an empty string.
|
|
5
|
+
Available functions: on(), setState(), getState(), schedule(), sendTo(), log(), createState(), setStateDelayed(), existsState(), httpGet(), httpPost(), exec(), formatDate(), $(), wait(), toInt(), toFloat(), readFile(), writeFile().`;let r=null,s=null,i=null;const E=6e4;function P(g,C,T){const y=[];for(const m of["javascript","typescript"]){const L=g.languages.registerInlineCompletionsProvider(m,{disposeInlineCompletions(){},provideInlineCompletions(l,t,D,c){return new Promise(n=>{if(r&&(r.cancel(),r=null),s&&clearTimeout(s),c.isCancellationRequested){n(void 0);return}s=setTimeout(async()=>{if(c.isCancellationRequested){n(void 0);return}const d=Object.keys(T)[0];if(!d){n(void 0);return}if(!i||Date.now()-i.ts>E)try{const e=await C.getObject(d);i={native:(e==null?void 0:e.native)||{},ts:Date.now()}}catch{n(void 0);return}const h=(i.native.gptKey||"").trim(),b=(i.native.claudeKey||"").trim(),v=(i.native.geminiKey||"").trim(),w=(i.native.deepseekKey||"").trim(),S=(i.native.gptBaseUrl||"").trim(),I=(i.native.gptBaseUrlKey||"").trim();let a="",o="openai",N="";if(S)a=I,o="openai",N=S;else if(h)a=h,o="openai";else if(w)a=w,o="deepseek";else if(b)a=b,o="anthropic";else if(v)a=v,o="gemini";else{n(void 0);return}const O=window.localStorage.getItem("openai-model")||"",U=l.getLineCount(),x=Math.max(1,t.lineNumber-50),B=Math.min(U,t.lineNumber+10);let p="";for(let e=x;e<t.lineNumber;e++)p+=`${l.getLineContent(e)}
|
|
6
|
+
`;p+=l.getLineContent(t.lineNumber).substring(0,t.column-1);let R=l.getLineContent(t.lineNumber).substring(t.column-1);for(let e=t.lineNumber+1;e<=B;e++)R+=`
|
|
7
|
+
${l.getLineContent(e)}`;let f=!1;r={cancel:()=>{f=!0}},c.onCancellationRequested(()=>{f=!0});try{const e=await C.sendTo(d,"chatCompletion",{timeout:15e3,apiKey:a,baseUrl:N,model:O,provider:o,messages:[{role:"system",content:M},{role:"user",content:`${p}<CURSOR>${R}`}]});if(f||c.isCancellationRequested){n(void 0);return}if(e.error||!e.content){n(void 0);return}let u=e.content.trim();const K=u.match(/```\w*\n?([\s\S]*?)```/);if(K&&(u=K[1].trim()),!u){n(void 0);return}n({items:[{insertText:u,range:new g.Range(t.lineNumber,t.column,t.lineNumber,t.column)}]})}catch{n(void 0)}r=null},800)})}});y.push(L)}return{dispose:()=>{s&&clearTimeout(s),r&&r.cancel(),y.forEach(m=>m.dispose())}}}export{P as registerAiInlineProvider};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c,j as s}from"./createSvgIcon-
|
|
1
|
+
import{c,j as s}from"./createSvgIcon-DYs_tNrE.js";const o=c(s.jsx("path",{d:"M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3m3-10H5V5h10z"}),"Save");export{o as S};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as e}from"./createSvgIcon-
|
|
2
|
-
return false`:t.source}}componentDidMount(){setTimeout(()=>{var t;try{(t=window.document.getElementById("source-text-area"))==null||t.focus()}catch{}},100)}handleCancel(){this.props.onClose(!1)}handleOk(){(!this.props.isReturn||this.state.source.includes("return "))&&this.props.onClose(this.state.source)}onChange(t){this.setState({changed:!0,source:t})}render(){return e.jsxs(l,{onClose:()=>!1,maxWidth:"lg",sx:{"& .MuiDialog-paper":s.dialog},fullWidth:!0,open:!0,"aria-labelledby":"source-dialog-title",children:[e.jsx(c,{id:"source-dialog-title",children:a.I18n.t("Function editor")}),e.jsxs(h,{style:s.fullHeight,children:[this.props.args&&e.jsxs(o,{sx:s.args,children:[e.jsx(o,{component:"span",sx:s.argsTitle,children:a.I18n.t("function (")}),this.props.args,e.jsx(o,{component:"span",sx:s.argsTitle,children:")"})]},"arguments"),e.jsx(p,{triggerPrettier:1,adapterName:this.props.adapterName,runningInstances:this.props.runningInstances,style:{...s.textArea,height:this.props.args?"calc(100% - 30px)":"100%"},name:"blockly",socket:this.props.socket,readOnly:!1,checkJs:!1,changed:this.state.changed,code:this.state.source,isDark:this.props.themeType==="dark",onChange:t=>this.onChange(t),language:"javascript"},"scriptEditor")]}),e.jsxs(d,{children:[e.jsx(i,{variant:"contained",onClick:()=>this.handleOk(),color:"primary",startIcon:e.jsx(m,{}),children:a.I18n.t("Save")}),e.jsx(i,{color:"grey",variant:"contained",onClick:()=>this.handleCancel(),startIcon:e.jsx(g,{}),children:a.I18n.t("Cancel")})]})]})}}export{
|
|
1
|
+
import{j as e}from"./createSvgIcon-DYs_tNrE.js";import{a as n}from"./iobroker_javascript__loadShare__react__loadShare__.mjs-CTZOFJS2.js";import{_ as l,a as c,b as h,z as o,h as d,i}from"./iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-CV1_X-Lf.js";import{_ as a}from"./iobroker_javascript__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__.mjs-DkBjPSMw.js";import p from"./ScriptEditorVanillaMonaco-cB_90T0P.js";import{S as m}from"./Save-CkuNSiWL.js";import{a as g}from"./index-wHNMOf-c.js";import"./iobroker_javascript__loadShare__react__loadShare__.mjs_commonjs-proxy-CE9lvhW8.js";import"./iobroker_javascript__loadShare__prop_mf_2_types__loadShare__.mjs-BCtSFofY.js";import"./preload-helper-BDBacUwf.js";const s={textArea:{width:"calc(100% - 10px)",resize:"none"},dialog:{height:"95%"},fullHeight:{height:"100%",overflow:"hidden"},args:r=>({color:r.palette.mode==="dark"?"white":"black",height:30,width:"100%",fontSize:16}),argsTitle:r=>({color:r.palette.mode==="dark"?"white":"black",fontWeight:"bold"})};class w extends n.Component{constructor(t){super(t),this.state={changed:!1,source:!t.source&&t.isReturn?`
|
|
2
|
+
return false`:t.source}}componentDidMount(){setTimeout(()=>{var t;try{(t=window.document.getElementById("source-text-area"))==null||t.focus()}catch{}},100)}handleCancel(){this.props.onClose(!1)}handleOk(){(!this.props.isReturn||this.state.source.includes("return "))&&this.props.onClose(this.state.source)}onChange(t){this.setState({changed:!0,source:t})}render(){return e.jsxs(l,{onClose:()=>!1,maxWidth:"lg",sx:{"& .MuiDialog-paper":s.dialog},fullWidth:!0,open:!0,"aria-labelledby":"source-dialog-title",children:[e.jsx(c,{id:"source-dialog-title",children:a.I18n.t("Function editor")}),e.jsxs(h,{style:s.fullHeight,children:[this.props.args&&e.jsxs(o,{sx:s.args,children:[e.jsx(o,{component:"span",sx:s.argsTitle,children:a.I18n.t("function (")}),this.props.args,e.jsx(o,{component:"span",sx:s.argsTitle,children:")"})]},"arguments"),e.jsx(p,{triggerPrettier:1,adapterName:this.props.adapterName,runningInstances:this.props.runningInstances,style:{...s.textArea,height:this.props.args?"calc(100% - 30px)":"100%"},name:"blockly",socket:this.props.socket,readOnly:!1,checkJs:!1,changed:this.state.changed,code:this.state.source,isDark:this.props.themeType==="dark",onChange:t=>this.onChange(t),language:"javascript"},"scriptEditor")]}),e.jsxs(d,{children:[e.jsx(i,{variant:"contained",onClick:()=>this.handleOk(),color:"primary",startIcon:e.jsx(m,{}),children:a.I18n.t("Save")}),e.jsx(i,{color:"grey",variant:"contained",onClick:()=>this.handleCancel(),startIcon:e.jsx(g,{}),children:a.I18n.t("Cancel")})]})]})}}export{w as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as f}from"./preload-helper-BDBacUwf.js";import{j as r}from"./createSvgIcon-DYs_tNrE.js";import{a as y}from"./iobroker_javascript__loadShare__react__loadShare__.mjs-CTZOFJS2.js";import{_ as S,a as v,b as C,h as w,i as D,Q as T,o as k,$ as E}from"./iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-CV1_X-Lf.js";import{n as b,Z as _}from"./index-wHNMOf-c.js";import{_ as u}from"./iobroker_javascript__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__.mjs-DkBjPSMw.js";import"./iobroker_javascript__loadShare__react__loadShare__.mjs_commonjs-proxy-CE9lvhW8.js";import"./iobroker_javascript__loadShare__prop_mf_2_types__loadShare__.mjs-BCtSFofY.js";function O(g){return/^script\.js\.global\./.test(g)}let L=0;function N(g){const t=/\x1b\[[0-9;]*m/g;return g.replace(t,"")}class F extends y.Component{monacoDiv=null;editor=null;monaco=window.monaco;get monacoTS(){var t,i;return(i=(t=this.monaco)==null?void 0:t.languages)==null?void 0:i.typescript}insert="";originalCode;runningInstancesStr;monacoCounter=0;location;breakpoints;lastSearch="";typings={};decorations=[];datapointProviderDisposable=null;inlineProviderDisposable=null;triggerPrettier;contentChangeDisposable=null;mouseDownDisposable=null;constructor(t){super(t),this.state={name:"current",isDark:t.isDark||!1,language:t.language||"javascript",readOnly:t.readOnly||!1,alive:!0,check:!1,searchText:this.props.searchText||"",typingsLoaded:!1,showError:null},this.triggerPrettier=t.triggerPrettier,this.runningInstancesStr=JSON.stringify(this.props.runningInstances),this.originalCode=t.code||"",this.monacoDiv=y.createRef()}waitForMonaco(t){var e,s,o,n;let i=!!((s=(e=this.monacoTS)==null?void 0:e.typescriptDefaults)!=null&&s.getCompilerOptions);if(!i||!this.props.runningInstances){if(this.monaco=window.monaco,i=!!((n=(o=this.monacoTS)==null?void 0:o.typescriptDefaults)!=null&&n.getCompilerOptions),this.monacoCounter++,!i&&this.monacoCounter<20){console.log("wait for monaco loaded"),setTimeout(()=>this.waitForMonaco(t),200);return}this.monacoCounter>=20&&console.error("Cannot load monaco!")}else t&&t()}loadTypings(t){if(!this.editor)return;t||=this.props.runningInstances;const i=t&&Object.keys(t).find(e=>t==null?void 0:t[e]);i&&this.props.socket.sendTo(i.replace("system.adapter.",""),"loadTypings",null).then(e=>{this.setState({alive:!0,check:!0,typingsLoaded:!0}),this.setTypeCheck(!0),e.typings?(this.typings=e.typings,this.setEditorTypings(this.state.name)):console.error(`failed to load typings: ${e.error}`)})}componentDidMount(){var e,s,o,n,l,d,h,p;let t=!!((s=(e=this.monacoTS)==null?void 0:e.typescriptDefaults)!=null&&s.getCompilerOptions);if((!t||!this.props.runningInstances)&&(this.monaco=window.monaco,t=!!((n=(o=this.monacoTS)==null?void 0:o.typescriptDefaults)!=null&&n.getCompilerOptions),!t)){console.log("wait for monaco loaded..."),this.waitForMonaco(()=>this.componentDidMount());return}if(!this.editor&&t&&this.monaco){console.log("Init editor"),(d=(l=this.props).onRegisterSelect)==null||d.call(l,()=>{var a;if(this.editor){const m=this.editor.getSelection();if(m)return(a=this.editor.getModel())==null?void 0:a.getValueInRange(m)}});const c=this.monacoTS.typescriptDefaults.getCompilerOptions();c.allowJs=!0,c.checkJs=this.props.checkJs!==!1,c.noLib=!0,c.lib=[],c.useUnknownInCatchVariables=!1,c.moduleResolution=this.monacoTS.ModuleResolutionKind.NodeJs,c.target=this.monacoTS.ScriptTarget.ESNext,c.module=this.monacoTS.ModuleKind.ESNext,c.allowNonTsExtensions=!0,this.monacoTS.typescriptDefaults.setCompilerOptions(c),this.setTypeCheck(!1),(h=this.monacoDiv)!=null&&h.current&&(this.editor=this.monaco.editor.create((p=this.monacoDiv)==null?void 0:p.current,{lineNumbers:"on",scrollBeyondLastLine:!1,automaticLayout:!0,glyphMargin:!!this.props.breakpoints,colorDecorators:!0}),this.contentChangeDisposable=this.editor.onDidChangeModelContent(()=>this.onChange()),this.monaco&&!this.datapointProviderDisposable&&f(async()=>{const{registerDatapointProvider:a}=await import("./AiDatapointProvider-B0i3I5Fm.js");return{registerDatapointProvider:a}},[],import.meta.url).then(({registerDatapointProvider:a})=>{this.monaco&&(this.datapointProviderDisposable=a(this.monaco,this.props.socket))}).catch(()=>{}),this.props.aiCompletionsEnabled&&this.monaco&&!this.inlineProviderDisposable&&f(async()=>{const{registerAiInlineProvider:a}=await import("./AiInlineProvider-Dd7eKxk4.js");return{registerAiInlineProvider:a}},[],import.meta.url).then(({registerAiInlineProvider:a})=>{this.monaco&&(this.inlineProviderDisposable=a(this.monaco,this.props.socket,this.props.runningInstances))}).catch(()=>{}),this.loadTypings(),this.props.onForceSave&&this.editor.addCommand(this.monaco.KeyMod.CtrlCmd|this.monaco.KeyCode.KeyS,()=>this.props.onForceSave&&this.props.onForceSave()),setTimeout(()=>{this.highlightText(this.state.searchText),this.location=this.props.location||void 0,this.breakpoints=this.props.breakpoints,this.showDecorators()}))}const i={selectOnLineNumbers:!0,scrollBeyondLastLine:!1,automaticLayout:!0,readOnly:this.state.readOnly,language:this.state.language,isDark:this.state.isDark};this.setEditorOptions(i),this.editor&&(this.editor.focus(),this.editor.setValue(this.originalCode),this.props.onToggleBreakpoint&&(this.mouseDownDisposable=this.editor.onMouseDown(c=>{var m;const a=c.target;this.props.onToggleBreakpoint&&((m=a.detail)==null?void 0:m.glyphMarginLeft)!==void 0&&a.position&&this.props.onToggleBreakpoint(a.position.lineNumber-1)})))}setEditorOptions(t){var i;t&&(t.language&&this.setEditorLanguage(t.language),this.editor&&(t.readOnly!==void 0&&this.editor.updateOptions({readOnly:t.readOnly}),t.lineWrap!==void 0&&this.editor.updateOptions({wordWrap:t.lineWrap?"on":"off"})),t.typeCheck!==void 0&&this.setTypeCheck(t.typeCheck),t.isDark!==void 0&&((i=this.monaco)==null||i.editor.setTheme(t.isDark?"vs-dark":"vs")))}componentWillUnmount(){var t,i,e,s,o,n;(t=this.contentChangeDisposable)==null||t.dispose(),this.contentChangeDisposable=null,(i=this.mouseDownDisposable)==null||i.dispose(),this.mouseDownDisposable=null,(e=this.datapointProviderDisposable)==null||e.dispose(),this.datapointProviderDisposable=null,f(async()=>{const{clearDatapointCache:l}=await import("./AiDatapointProvider-B0i3I5Fm.js");return{clearDatapointCache:l}},[],import.meta.url).then(({clearDatapointCache:l})=>l()).catch(()=>{}),(s=this.inlineProviderDisposable)==null||s.dispose(),this.inlineProviderDisposable=null,this.editor&&((n=(o=this.props).onRegisterSelect)==null||n.call(o,null),this.editor.dispose(),this.editor=null)}async doPrettier(){var e,s,o,n;const t=this.props.runningInstances&&Object.keys(this.props.runningInstances).find(l=>{var d;return(d=this.props.runningInstances)==null?void 0:d[l]});if(!t){window.alert(u.I18n.t("No script adapter instance found to format the code"));return}const i=await this.props.socket.sendTo(t.replace("system.adapter.",""),"prettier",{code:(e=this.editor)==null?void 0:e.getValue(),type:this.state.language});i.error?this.setState({showError:{title:u.I18n.t("Error formatting code"),message:N(i.error)}}):i.code&&((s=this.editor)==null||s.setValue(i.code),(n=(o=this.props).onChange)==null||n.call(o,i.code),this.showDecorators())}setEditorLanguage(t){var e,s;if(!this.editor)return;const i=this.editor.getModel();if(i){const o=i.getValue(),n=i.uri.path,l=typeof n=="string"&&n.includes(".")?n.substring(0,n.lastIndexOf(".")):"index",d=t==="javascript"?"js":t==="typescript"?"ts":t;i.dispose();const h=t==="javascript"||t==="typescript"?"typescript":t,p=(e=this.monaco)==null?void 0:e.editor.createModel(o,h,this.monaco.Uri.from({scheme:window.location.protocol.replace(":",""),path:`${l}${L++}.${d}`}));p&&(this.editor.setModel(p),(s=this.contentChangeDisposable)==null||s.dispose(),this.contentChangeDisposable=this.editor.onDidChangeModelContent(()=>this.onChange()))}}setTypeCheck(t){var e,s;const i={noSemanticValidation:!this.state.alive||!t,noSyntaxValidation:!this.state.alive};(e=this.monacoTS)==null||e.typescriptDefaults.setDiagnosticsOptions(i),(s=this.monacoTS)==null||s.javascriptDefaults.setDiagnosticsOptions({noSemanticValidation:!this.state.alive||!t,noSyntaxValidation:!this.state.alive})}setEditorTypings(t=""){var o,n,l,d;const i=O(t),e=`${t}.d.ts`,s=[];for(const h of Object.keys(this.typings))i&&(h==="global.d.ts"||h.startsWith("script.js.global")&&h!==e)||s.push({filePath:h,content:this.typings[h]});if((n=(o=this.monacoTS)==null?void 0:o.typescriptDefaults)!=null&&n.setExtraLibs)this.monacoTS.typescriptDefaults.setExtraLibs(s);else if((d=(l=this.monacoTS)==null?void 0:l.typescriptDefaults)!=null&&d.addExtraLib){const h=this.monacoTS.typescriptDefaults.getExtraLibs();s.forEach(p=>{!h[p.filePath]&&this.monaco&&this.monacoTS.typescriptDefaults.addExtraLib(p.content,p.filePath)})}}undo(){var t;(t=this.editor)==null||t.trigger("toolbar","undo",null)}redo(){var t;(t=this.editor)==null||t.trigger("toolbar","redo",null)}insertTextIntoEditor(t){if(!this.editor||!this.monaco)return;const i=this.editor.getSelection();if(i){const e=new this.monaco.Range(i.startLineNumber,i.startColumn,i.endLineNumber,i.endColumn);this.editor.executeEdits("",[{range:e,text:t,forceMoveMarkers:!0}])}this.editor.focus()}highlightText(t){var e;if(!this.editor||!this.monaco)return;const i=t?(e=this.editor.getModel())==null?void 0:e.findMatches(t,!0,!1,!1,null,!0):void 0;if(i!=null&&i.length)i.forEach(s=>{var o;return(o=this.editor)==null?void 0:o.setSelection(s.range)}),this.editor.revealLine(i[0].range.startLineNumber);else{const s=this.editor.getPosition();if(s){const o=s.lineNumber,n=s.column;this.editor.setSelection(new this.monaco.Range(o,n,o,n))}}}showDecorators(){var i;const t=[];if(this.location&&this.monaco&&(t.push({range:new this.monaco.Range(this.location.lineNumber+1,(this.location.columnNumber||0)+1,this.location.lineNumber+1,1e3),options:{isWholeLine:!1,className:this.props.isDark?"monacoCurrentLineDark":"monacoCurrentLine"}}),t.push({range:new this.monaco.Range(this.location.lineNumber+1,0,this.location.lineNumber+1,0),options:{isWholeLine:!0,className:this.props.isDark?"monacoCurrentFullLineDark":"monacoCurrentFullLine"}})),(i=this.breakpoints)==null||i.forEach(e=>{this.monaco&&t.push({range:new this.monaco.Range(e.location.lineNumber+1,0,e.location.lineNumber+1,100),options:{isWholeLine:!0,glyphMarginClassName:this.props.isDark?"monacoBreakPointDark":"monacoBreakPoint"}})}),this.editor){const e=this.editor.getModel();e&&(this.decorations=e.deltaDecorations(this.decorations,t))}}initNewScript(t,i){var e;this.setState({name:t}),this.originalCode=i||"",(e=this.editor)==null||e.setValue(i||""),this.highlightText(this.lastSearch),this.showDecorators(),this.setEditorTypings(t)}scrollToLineIfNeeded(t){if(this.editor){const i=this.editor.getVisibleRanges();(!i||!i[0]||i[0].startLineNumber>t||t>i[0].endLineNumber)&&this.editor.revealLineInCenter(t)}}UNSAFE_componentWillReceiveProps(t){const i={};this.state.name!==t.name&&this.initNewScript(t.name,t.code),JSON.stringify(t.runningInstances)!==this.runningInstancesStr&&(this.runningInstancesStr=JSON.stringify(t.runningInstances),this.state.typingsLoaded||this.loadTypings(t.runningInstances)),this.editor&&!t.changed&&(t.code!==this.originalCode||t.code!==this.editor.getValue())&&(this.originalCode=t.code||"",this.editor.setValue(this.originalCode),this.showDecorators(),this.location&&this.scrollToLineIfNeeded(this.location.lineNumber+1)),t.searchText!==this.lastSearch&&(this.lastSearch=t.searchText||"",this.highlightText(this.lastSearch)),JSON.stringify(t.location)!==JSON.stringify(this.location)&&JSON.stringify(t.breakpoints)!==JSON.stringify(this.breakpoints)?(this.location=t.location||void 0,this.breakpoints=t.breakpoints,this.showDecorators(),this.editor&&this.location&&this.scrollToLineIfNeeded(this.location.lineNumber+1)):JSON.stringify(t.breakpoints)!==JSON.stringify(this.breakpoints)?(this.breakpoints=t.breakpoints,this.showDecorators()):JSON.stringify(t.location)!==JSON.stringify(this.location)&&(this.location=t.location||void 0,this.showDecorators(),this.editor&&this.location&&this.scrollToLineIfNeeded(this.location.lineNumber+1)),this.state.language!==(t.language||"javascript")?(this.setState({language:t.language||"javascript"}),i.language=t.language||"javascript"):this.state.readOnly!==(t.readOnly||!1)?(this.setState({readOnly:t.readOnly||!1}),i.readOnly=t.readOnly):this.state.isDark!==(t.isDark||!1)&&(this.setState({isDark:t.isDark||!1}),i.isDark=t.isDark),this.setEditorOptions(i),t.aiCompletionsEnabled!==this.props.aiCompletionsEnabled&&(t.aiCompletionsEnabled&&this.monaco&&!this.inlineProviderDisposable?f(async()=>{const{registerAiInlineProvider:e}=await import("./AiInlineProvider-Dd7eKxk4.js");return{registerAiInlineProvider:e}},[],import.meta.url).then(({registerAiInlineProvider:e})=>{this.monaco&&(this.inlineProviderDisposable=e(this.monaco,this.props.socket,this.props.runningInstances))}).catch(()=>{}):!t.aiCompletionsEnabled&&this.inlineProviderDisposable&&(this.inlineProviderDisposable.dispose(),this.inlineProviderDisposable=null)),this.insert!==t.insert&&(this.insert=t.insert||"",this.insert&&(console.log(`Insert text: ${this.insert}`),setTimeout(e=>{this.insertTextIntoEditor(e),setTimeout(()=>this.props.onInserted&&this.props.onInserted(),100)},100,this.insert)))}onChange(){var t,i;!this.props.readOnly&&this.editor&&((i=(t=this.props).onChange)==null||i.call(t,this.editor.getValue()))}renderErrorDialog(){return this.state.showError?this.state.showError.full?r.jsxs(S,{open:!0,maxWidth:"md",onClose:()=>this.setState({showError:null}),children:[r.jsx(v,{children:this.state.showError.title||u.I18n.t("Error")}),r.jsx(C,{children:r.jsx("pre",{children:r.jsx("code",{children:this.state.showError.message})})}),r.jsx(w,{children:r.jsxs(D,{variant:"contained",startIcon:r.jsx(b,{}),onClick:()=>this.setState({showError:null}),children:[u.I18n.t("Close")," "]})})]}):r.jsx(T,{open:!0,autoHideDuration:5e3,onClose:()=>this.setState({showError:null}),message:this.state.showError.title,action:r.jsxs(y.Fragment,{children:[r.jsx(D,{color:"secondary",size:"small",onClick:()=>this.setState({showError:{...this.state.showError,full:!0}}),children:u.I18n.t("More")}),r.jsx(k,{size:"small","aria-label":"close",color:"inherit",onClick:()=>this.setState({showError:null}),children:r.jsx(b,{fontSize:"small"})})]})}):null}render(){var t;return!((t=this.monacoTS)!=null&&t.typescriptDefaults)||!this.props.runningInstances?(setTimeout(()=>{this.monaco=window.monaco,this.forceUpdate()},200),null):(this.props.triggerPrettier!==this.triggerPrettier&&(this.triggerPrettier=this.props.triggerPrettier,setTimeout(()=>this.doPrettier().catch(i=>console.error("Error formatting code:",i)),50)),r.jsxs("div",{ref:this.monacoDiv,style:{...this.props.style,width:"100%",height:"100%",overflow:"hidden",position:"relative"},children:[this.renderErrorDialog(),!this.state.check&&r.jsx(E,{size:"small",title:u.I18n.t("Check is not active, because javascript adapter is disabled"),style:{bottom:10,right:10,opacity:.5,position:"absolute",zIndex:1,background:"red",color:"white"},color:"secondary",children:r.jsx(_,{})})]}))}}export{F as default};
|