iobroker.javascript 10.2.5 → 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.
Files changed (205) hide show
  1. package/README.md +26 -23
  2. package/admin/assets/AiChatPanel-BjRIKaXG.js +27 -0
  3. package/admin/assets/{AiChatService-BOL3J2Jd.js → AiChatService-DP1EmVk2.js} +3 -3
  4. package/admin/assets/AiDiffView-DeynDw7L.js +1 -0
  5. package/admin/assets/{AiInlineProvider-BIlcrTkS.js → AiInlineProvider-jkEIJJJ-.js} +1 -1
  6. package/admin/assets/BlocklyEditor-DhwThchX.js +301 -0
  7. package/admin/assets/Compile-B0uHjrBE.css +1 -0
  8. package/admin/assets/Compile-e8N5zI-J.js +165 -0
  9. package/admin/assets/Debugger-BDQUKM1K.js +15 -0
  10. package/admin/assets/Diff--plofAtP.js +1 -0
  11. package/admin/assets/{Documentation-Bc0RmoEF.js → Documentation-D3E0U4AK.js} +4 -4
  12. package/admin/assets/ExpandMore-Dio4GeHC.js +1 -0
  13. package/admin/assets/FbEditor-B8S-mCvc.css +1 -0
  14. package/admin/assets/FbEditor-BjLPNzpK.js +15 -0
  15. package/admin/assets/History-Ewi5YEEn.js +1 -0
  16. package/admin/assets/Import-6Mm2vrM2.js +1 -0
  17. package/admin/assets/MonacoDiff-BYvG7IqB.js +1 -0
  18. package/admin/assets/NotificationsActive-CuNfWVJM.js +1 -0
  19. package/admin/assets/RulesEditor--YX6ETsU.js +1 -0
  20. package/admin/assets/{ScriptEditor-CEHpEFp7.js → ScriptEditor-BadPC8Mf.js} +2 -2
  21. package/admin/assets/ScriptEditorVanillaMonaco-BnAmy59d.js +3 -0
  22. package/admin/assets/Send-Pz1eveU5.js +1 -0
  23. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-Ceh8EDcF.js +1 -0
  24. 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
  25. 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
  26. package/admin/assets/aiPromptBuilder-Co6AqZwx.js +1 -0
  27. package/admin/assets/{blockly-fcfyKYzp.js → blockly-B0t_IRJQ.js} +1 -1
  28. package/admin/assets/blocklyTheme-iZoge1S9.js +1 -0
  29. package/admin/assets/blocks_action-Ctn5A1AU.js +1 -0
  30. package/admin/assets/{blocks_convert-BP2RjhQH.js → blocks_convert-BI0lf0sf.js} +1 -1
  31. package/admin/assets/blocks_logic-o49klUX_.js +1 -0
  32. package/admin/assets/blocks_number-DZtyWFyR.js +1 -0
  33. package/admin/assets/blocks_object-BuzGCxVr.js +1 -0
  34. package/admin/assets/blocks_procedures-jn9sIYmR.js +3 -0
  35. package/admin/assets/blocks_sendto-Coui8w1H.js +5 -0
  36. package/admin/assets/blocks_switch-CeRZizTM.js +2 -0
  37. package/admin/assets/blocks_system-CaBPIC40.js +1 -0
  38. package/admin/assets/blocks_text-DeDtPYWf.js +1 -0
  39. package/admin/assets/blocks_time-CTXQH3Lm.js +1 -0
  40. package/admin/assets/blocks_timeout-D8IOKOb-.js +1 -0
  41. package/admin/assets/{blocks_trigger-CnmXLCUE.js → blocks_trigger-zuuXJbhb.js} +2 -2
  42. package/admin/assets/{cronHoverProvider-CcIFAhVy.js → cronHoverProvider-Curcjz4m.js} +1 -1
  43. package/admin/assets/dist-CzitsFi7.js +1 -0
  44. package/admin/assets/field_cron-RgLY53_S.js +1 -0
  45. package/admin/assets/field_oid-rBhotXJe.js +1 -0
  46. package/admin/assets/field_script-CU7g3-oB.js +1 -0
  47. package/admin/assets/helpers-BZgjFQNf.js +1 -0
  48. package/admin/assets/helpers-BwllSRzJ.js +1 -0
  49. package/admin/assets/hostInit-CrHjJGJJ.js +1 -0
  50. package/admin/assets/index-BHhhebRG.css +1 -0
  51. package/admin/assets/index-Bmmscq2G.js +157 -0
  52. package/admin/assets/{inlineChatWidget-N8xIkvxX.js → inlineChatWidget-ChchJD9a.js} +2 -2
  53. package/admin/assets/{inlineDiffController-BuqYsKKq.js → inlineDiffController-ly6qX4jk.js} +2 -2
  54. package/admin/assets/loadBlocks-BcFtthDb.js +117 -0
  55. package/admin/assets/loadMonaco-BVOEahNw.js +1 -0
  56. package/admin/assets/{mf-entry-bootstrap-0-a5a39621.js → mf-entry-bootstrap-0-6db6c4fc.js} +3 -3
  57. package/admin/assets/pendingShares-mBGPbRwZ.js +2 -0
  58. package/admin/assets/reactour.esm-Dk3aGxKn.js +137 -0
  59. package/admin/assets/{stateHoverProvider-BYAbe1Ay.js → stateHoverProvider-wAsP-THx.js} +1 -1
  60. package/admin/assets/tileFbd-CWAy7R7m.svg +85 -0
  61. package/admin/assets/utils-DUKzLJUz.js +4 -0
  62. package/admin/assets/vite-preload-helper-DjNwdemH.js +1 -0
  63. package/admin/custom/assets/Components-fDcxCyN4.js +1 -0
  64. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-BraOrMSu.js +1 -0
  65. 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
  66. 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
  67. 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
  68. 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
  69. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__date_mf_2_fns__loadShare__.js-Djg9OMcQ.js +1 -0
  70. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__leaflet__loadShare__.js-D9EyCd42.js +1 -0
  71. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__loadShare__shared-Hb6V6BnJ.js +2 -0
  72. 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
  73. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__198282747311932__prebuild__leaflet__prebuild__-CHjWtrkp.js +1 -0
  74. 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
  75. package/admin/custom/assets/dist-CzitsFi7.js +1 -0
  76. package/admin/custom/assets/helpers-BZgjFQNf.js +1 -0
  77. package/admin/custom/assets/hostInit-akwaQLq8.js +1 -0
  78. package/admin/custom/assets/index-BkItz-nL.js +1 -0
  79. package/admin/custom/assets/{lib-BmDlTzq2.js → lib-CADOx2YN.js} +1 -1
  80. package/admin/custom/assets/{mf-entry-bootstrap-0-ad1cd7d0.js → mf-entry-bootstrap-0-3c4565e0.js} +3 -3
  81. package/admin/custom/assets/pendingShares-TCMDgBLn.js +2 -0
  82. package/admin/custom/assets/utils-DUKzLJUz.js +4 -0
  83. package/admin/custom/assets/vite-preload-helper-DjNwdemH.js +1 -0
  84. package/admin/custom/customComponents.js +2 -2
  85. package/admin/custom/i18n/de.json +19 -1
  86. package/admin/custom/i18n/en.json +19 -1
  87. package/admin/custom/i18n/es.json +19 -1
  88. package/admin/custom/i18n/fr.json +19 -1
  89. package/admin/custom/i18n/it.json +19 -1
  90. package/admin/custom/i18n/nl.json +19 -1
  91. package/admin/custom/i18n/pl.json +19 -1
  92. package/admin/custom/i18n/pt.json +19 -1
  93. package/admin/custom/i18n/ru.json +19 -1
  94. package/admin/custom/i18n/uk.json +19 -1
  95. package/admin/custom/i18n/zh-cn.json +19 -1
  96. package/admin/i18n/de.json +13 -1
  97. package/admin/i18n/en.json +13 -1
  98. package/admin/i18n/es.json +13 -1
  99. package/admin/i18n/fr.json +13 -1
  100. package/admin/i18n/it.json +13 -1
  101. package/admin/i18n/nl.json +13 -1
  102. package/admin/i18n/pl.json +13 -1
  103. package/admin/i18n/pt.json +13 -1
  104. package/admin/i18n/ru.json +13 -1
  105. package/admin/i18n/uk.json +13 -1
  106. package/admin/i18n/zh-cn.json +13 -1
  107. package/admin/jsonConfig.json +274 -86
  108. package/admin/mf-manifest.json +1 -1
  109. package/admin/mf-stats.json +1 -1
  110. package/admin/remoteEntry.js +2 -2
  111. package/admin/tab.html +3 -7
  112. package/build/lib/aiProviderResolver.js +145 -25
  113. package/build/lib/aiProviderResolver.js.map +1 -1
  114. package/build/lib/anthropicAdapter.js +37 -0
  115. package/build/lib/anthropicAdapter.js.map +1 -1
  116. package/build/lib/fb/analyze.js +288 -0
  117. package/build/lib/fb/analyze.js.map +1 -0
  118. package/build/lib/fb/blocks.js +605 -0
  119. package/build/lib/fb/blocks.js.map +1 -0
  120. package/build/lib/fb/generate.js +326 -0
  121. package/build/lib/fb/generate.js.map +1 -0
  122. package/build/lib/fb/graph.js +240 -0
  123. package/build/lib/fb/graph.js.map +1 -0
  124. package/build/lib/fb/index.js +57 -0
  125. package/build/lib/fb/index.js.map +1 -0
  126. package/build/lib/fb/js.js +33 -0
  127. package/build/lib/fb/js.js.map +1 -0
  128. package/build/lib/fb/layout.js +205 -0
  129. package/build/lib/fb/layout.js.map +1 -0
  130. package/build/lib/fb/library.js +657 -0
  131. package/build/lib/fb/library.js.map +1 -0
  132. package/build/lib/fb/runtime.js +793 -0
  133. package/build/lib/fb/runtime.js.map +1 -0
  134. package/build/lib/fb/time.js +76 -0
  135. package/build/lib/fb/time.js.map +1 -0
  136. package/build/lib/fb/types.js +19 -0
  137. package/build/lib/fb/types.js.map +1 -0
  138. package/build/lib/fb/user.js +78 -0
  139. package/build/lib/fb/user.js.map +1 -0
  140. package/build/lib/inspect.js +66 -10
  141. package/build/lib/inspect.js.map +1 -1
  142. package/build/lib/javascript.d.ts +1 -1
  143. package/build/lib/mirror.js +28 -23
  144. package/build/lib/mirror.js.map +1 -1
  145. package/build/lib/sandbox.js +44 -0
  146. package/build/lib/sandbox.js.map +1 -1
  147. package/build/lib/scriptHistory.js +245 -0
  148. package/build/lib/scriptHistory.js.map +1 -0
  149. package/build/main.js +641 -32
  150. package/build/main.js.map +1 -1
  151. package/build/types.d.ts +20 -1
  152. package/docs/de/fbd.md +274 -0
  153. package/docs/en/fbd.md +260 -0
  154. package/io-package.json +55 -29
  155. package/package.json +7 -7
  156. package/admin/assets/AiChatPanel-oBeXbUFv.js +0 -27
  157. package/admin/assets/AiDiffView-C-KKjnJD.js +0 -1
  158. package/admin/assets/Debugger-DwHHsh9O.js +0 -15
  159. package/admin/assets/Error-DZ4vCykD.js +0 -1
  160. package/admin/assets/Import-Cu02ceLW.js +0 -1
  161. package/admin/assets/RulesEditor-QCbi1lV_.js +0 -1
  162. package/admin/assets/ScriptEditorVanillaMonaco-ChQmnk0p.js +0 -3
  163. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-CM95r358.js +0 -1
  164. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BEpNZh4U.js +0 -1217
  165. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-FeM77flT.js +0 -9
  166. package/admin/assets/aiPromptBuilder-DKler0UK.js +0 -1
  167. package/admin/assets/blocks_action-DywZVfRY.js +0 -1
  168. package/admin/assets/blocks_logic-CdTl5YZw.js +0 -1
  169. package/admin/assets/blocks_number-DXFd9Rva.js +0 -1
  170. package/admin/assets/blocks_object-by1uBDHi.js +0 -1
  171. package/admin/assets/blocks_procedures-BcJ7N70D.js +0 -3
  172. package/admin/assets/blocks_sendto-qIKzOAcV.js +0 -5
  173. package/admin/assets/blocks_switch-dLF6hSJl.js +0 -2
  174. package/admin/assets/blocks_system-DmX-SBy8.js +0 -1
  175. package/admin/assets/blocks_text-BI4zNU3o.js +0 -1
  176. package/admin/assets/blocks_time-BgYA4Y_4.js +0 -1
  177. package/admin/assets/blocks_timeout-DUzgMyAu.js +0 -1
  178. package/admin/assets/dist-D4uJqRBO.js +0 -4
  179. package/admin/assets/field_cron-Ba46q8Qc.js +0 -1
  180. package/admin/assets/field_oid-lWCjOzuq.js +0 -1
  181. package/admin/assets/field_script-BCWZHhnW.js +0 -1
  182. package/admin/assets/helpers-CnEjYAup.js +0 -1
  183. package/admin/assets/hostInit-CVybS7BB.js +0 -1
  184. package/admin/assets/index-B3s0zmWC.js +0 -871
  185. package/admin/assets/index-CXaeqPRy.css +0 -1
  186. package/admin/assets/pendingShares-DOAkyFMS.js +0 -1
  187. package/admin/assets/vite-preload-helper-CaC3yEL3.js +0 -1
  188. package/admin/custom/assets/Components-FkGDIlId.js +0 -1
  189. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-Cs88NUCd.js +0 -1
  190. 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
  191. 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
  192. 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
  193. 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
  194. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__date_mf_2_fns__loadShare__.js-CnhNjamd.js +0 -1
  195. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__loadShare__leaflet__loadShare__.js-Dz7BFJqH.js +0 -1
  196. 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
  197. 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
  198. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__37453319418803__prebuild__leaflet__prebuild__-xPcBaiTQ.js +0 -1
  199. 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
  200. package/admin/custom/assets/dist-D4uJqRBO.js +0 -4
  201. package/admin/custom/assets/hostInit-6oh4UY2k.js +0 -1
  202. package/admin/custom/assets/index-BrlyEy6J.js +0 -1
  203. package/admin/custom/assets/pendingShares-kV2kwejX.js +0 -1
  204. package/admin/custom/assets/vite-preload-helper-CaC3yEL3.js +0 -1
  205. /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
@@ -1,7 +1,7 @@
1
- import{t as e}from"./assets/vite-preload-helper-CaC3yEL3.js";import{a as t,t as n}from"./assets/dist-D4uJqRBO.js";({...t.global});var r=t.share;t.utils;var i={};typeof __VUE_HMR_RUNTIME__>`u`&&(globalThis.__VUE_HMR_RUNTIME__={createRecord(){},rerender(){},reload(){}});var a=`__mf_init__virtual:mf:__mfe_internal__iobroker_javascript__mf_owner__180366418666083__mf_v__runtimeInit__mf_v__.js__`,o=globalThis[a];if(!o){let e,t,n=new Promise((n,r)=>{e=n,t=r});o=globalThis[a]={initPromise:n,initResolve:e,initReject:t}}var s=o.initResolve,c=`__mf_module_cache__`;globalThis[c]||={share:{},remote:{}},globalThis[c].share||={},globalThis[c].remote||={};var l=globalThis[c];for(let e of Object.keys(l.share))if(e.startsWith(`default:`)){let t=e.slice(8);l.share[t]===void 0&&(l.share[t]=l.share[e])}else if(!e.includes(`:`)){let t=`default:`+e;l.share[t]===void 0&&(l.share[t]=l.share[e])}var u={},d=Array.isArray(`default`)?`default`:[`default`],f=`default`,p=`iobroker_javascript`,m=[[`react`,`prop-types`],[`react/jsx-runtime`,`react-dom`],[`react-dom/client`,`@mui/material`],[`@iobroker/gui-components`]],h,g;async function _(e){for(let t=0;;t++)try{return await e()}catch(e){throw e}}var v=Symbol(`mf.originalSharedProvider`),y={emit:e=>e},b=(e,t)=>{if(t!==`version-first`)return e;let n={};for(let[t,r]of Object.entries(e))n[t]=Object.assign({},r,{[v]:r});return n},x=(e,t)=>{if(!t)return;let n=Object.entries(e||{}),r=n.find(([,e])=>e===t);if(r)return{version:r[0],provider:t,registered:!0};if(typeof t.version==`string`&&t.version)return{version:t.version,provider:t,registered:!1};let i=n.filter(([,e])=>e===t||!!(t.from&&(e==null?void 0:e.from)===t.from));if(i.length===1)return{version:i[0][0],provider:t,registered:!1}},S=(e,t,n,i)=>{var a;if(!e||!n)return;let o=Object.fromEntries(Object.entries(e).filter(([,e])=>{var t;return(e==null||(t=e.shareConfig)==null?void 0:t.import)!==!1}));if(Object.keys(o).length===0)return;let s=Array.isArray(n.scope)?n.scope:[n.scope||`default`],c=b(o,i),l={};for(let e of s)l[e||`default`]={[t]:c};let u=(a=r.getRegisteredShare(l,t,{...n,scope:s,strategy:i},y))==null?void 0:a.shared;return(u==null?void 0:u[v])||u},C=(e,t,n,r)=>{var i;let a=e=>w(e,n),o=Object.fromEntries(Object.entries(e||{}).filter(([,e])=>{var t;return!a(e)&&(e==null||(t=e.shareConfig)==null?void 0:t.import)!==!1}));n!=null&&n.version&&((i=n.shareConfig)==null?void 0:i.import)!==!1&&(o[n.version]||(o[n.version]=n));let s=S(o,t,n,r);return a(s)?void 0:s},w=(e,t)=>e===t||!!(t!=null&&t.from&&(e==null?void 0:e.from)===t.from),T=(e,t,n,r,i,a,o,s,c)=>{var l,u;if(c!==`version-first`||!s)return;let d=t==null||(l=t.options)==null||(l=l.shared)==null?void 0:l[i],f=Array.isArray(d)?d.find(e=>(e==null?void 0:e.version)===a):void 0,p=((s==null?void 0:s.from)===(t==null||(u=t.options)==null?void 0:u.name)?s:void 0)||(w(f,s)?f:t?void 0:s);if(p)return e.some(e=>{var i,a;return e!==t&&(e==null||(i=e.options)==null?void 0:i.name)===(o==null?void 0:o.from)&&(e==null||(a=e.shareScopeMap)==null?void 0:a[r])===n})?p:void 0},E=(e,t,n,r,i,a,o,s,c)=>{let l=a.registered?T(e,t,n,r,i,a.version,a.provider,s,c):void 0,u=l||o;if(u&&(!a.registered||w(u,s)))return{provider:u,scopeRootProvider:l}};async function D(){return h||=_(()=>e(()=>import(`./assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-CM95r358.js`),[],import.meta.url)).catch(e=>{throw h=void 0,e}),h}async function O(){return i}async function k(e={},t=[],r={}){var i,a;let o=(e,t,n,r)=>{let i=(Array.isArray(r)?r[0]:r)||`default`,a=t||!n?e:e+`@`+n,o={canonical:i+`:`+a};return i==="default"&&(o.aliases=[a]),o},c=(e,t)=>{let n=e[t.canonical];if(n!==void 0)return n;let r=t.aliases||[];for(let n of r){if(!Object.prototype.hasOwnProperty.call(e,n))continue;let r=e[n];if(r!==void 0)return e[t.canonical]=r,r}},h=Symbol.for(`module-federation.shared-cache-listeners`),v=Symbol.for(`module-federation.shared-cache-owners`),y=e=>{let t=e[v];return t===void 0&&(t=Object.create(null),Object.defineProperty(e,v,{value:t,enumerable:!1,configurable:!1,writable:!1})),t},b=(e,t)=>{var n;return(n=e[v])==null?void 0:n[t.canonical]},T=(e,t,n,r)=>{var i;e[t.canonical]=n;let a=t.aliases||[];for(let t of a)Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0});let o=e[v];r===void 0?o&&delete o[t.canonical]:y(e)[t.canonical]=r;let s=(i=e[h])==null?void 0:i[t.canonical];if(s)for(let e of s)e(n);return n},O=Symbol.for(`module-federation.tree-shaking-shared-cache`),k=e=>{let t=e[O];return t===void 0&&(t=Object.create(null),Object.defineProperty(e,O,{value:t,enumerable:!1,configurable:!1,writable:!1})),t},A=(e,t,n,r)=>{if(!Array.isArray(n))return r;let i=[...new Set(n)].sort(),a=k(e),o=a[t.canonical]||=[],s=o.find(e=>e.providedExports.length===i.length&&e.providedExports.every((e,t)=>e===i[t]));return s?s.value=r:o.push({providedExports:i,value:r}),r},j=Symbol.for(`module-federation.tree-shaking-shared-selection-cache`),ee=e=>{let t=e[j];return t===void 0&&(t=Object.create(null),Object.defineProperty(e,j,{value:t,enumerable:!1,configurable:!1,writable:!1})),t},M=(e,t,n)=>{var r;let i=c(e,t);return i===void 0?(r=e[j])==null||(r=r[t.canonical])==null?void 0:r[n]:i},N=(e,t,n,r)=>{let i=ee(e),a=i[t.canonical]||=Object.create(null);return a[n]=r,r},P=((i=globalThis.__FEDERATION__)==null?void 0:i.__INSTANCES__)||[],F=(a=t.find(e=>e==null?void 0:e.from))==null?void 0:a.from,te=P.find(t=>{var n,r;return(t==null||(n=t.options)==null?void 0:n.name)===F&&(t==null||(r=t.shareScopeMap)==null?void 0:r.default)===e})||P.find(t=>{var n,r;return(t==null||(n=t.options)==null?void 0:n.name)!==p&&(t==null||(r=t.shareScopeMap)==null?void 0:r.default)===e}),I=Object.create(null),L=e=>{let t=Object.create(null);for(let[n,r]of Object.entries(e||{}))t[n]=Object.assign(Object.create(null),r);return t},R=(e,t)=>{var n;for(let[i,a]of Object.entries(((n=q.shareScopeMap)==null?void 0:n[e])||{}))for(let[e,n]of Object.entries(a||{})){var r;if(!n||n.get===((r=B[i])==null?void 0:r.get))continue;let a=t[i]||={};a[e]===void 0&&(a[e]=n)}},ne=(e,t)=>{R(e,t);let n=!te&&Object.values(t||{}).some(e=>Object.values(e||{}).some(V)),r=n?L(t):t;return I[e]={host:t,runtime:r,isWebpackScope:n},r},re=()=>{let e=Object.values(I).filter(({isWebpackScope:e})=>e);if(e.length!==0)for(let{host:t,runtime:n}of e)for(let[e,r]of Object.entries(t||{})){let t=n[e]||=Object.create(null);for(let[e,n]of Object.entries(r||{}))t[e]=n}},z=Object.create(null);for(let[t,n]of Object.entries(e)){let e=z[t]=Object.create(null);for(let[t,r]of Object.entries(n))e[t]=Object.assign({},r)}let{usedShared:B,usedRemotes:ie}=await D();function V(e){if(typeof(e==null?void 0:e.get)!=`function`)return!1;let t=Function.prototype.toString.call(e.get);return t.includes(`__webpack_require__`)||/\.\s*e\s*\([^)]*\)\s*\.then\s*\(/.test(t)}let ae=Object.values(z).some(e=>Object.values(e||{}).some(V)),oe=e=>{let t=e.split(`/`);return e.startsWith(`@`)?t.slice(0,2).join(`/`):t[0]},H=(t,n,r,i)=>{if(typeof C!=`function`)return;let a=oe(t),o=!i||a===t?[[t,n]]:[[t,n],[a,B[a]]];for(let[n,i]of o){if(!i)continue;let a=C(r?n===t?r:z[n]:z[n]??e[n],n,i,`version-first`);if(a)return a}},se=(e,t,n)=>{let r=H(e,t,n,!0);return r&&V(r)&&!r.lib&&!r.loaded?r:void 0};var U=u[f];if(U||=u[f]={from:p},t.indexOf(U)>=0)return;t.push(U);let ce=e=>{let t=e;for(let e=0;e<5;e++){let e=t==null?void 0:t.default;if(!e||typeof e!=`object`||Object.keys(e).length===0)break;let n=Object.keys(t).filter(e=>e!=="default").map(e=>t[e]);if(n.length>0&&n.some(e=>e!==void 0))break;t=e}return t},le=[],ue=globalThis.window===void 0?await Promise.all([]):[],W=`__mf_vite_runtime_share_load_id__`,de=0,G=new Map,K=new Map,q=n({name:p,remotes:ie,shared:B,plugins:[fe(),pe(),...le,...ue],shareStrategy:`version-first`});q.initShareScopeMap(`default`,ne(`default`,e));function fe(){return{name:`vite-share-pin-lifecycle-plugin`,resolveShare(e){var t;let n=(t=e.shareInfo)==null?void 0:t[W],r=n===void 0?void 0:K.get(n);if(!r)return e;let i=e.resolver;return e.resolver=(...e)=>(r.pinned.reapply(),i(...e)),r.pinned.reveal(),e}}}function pe(){return{name:`vite-real-name-snapshot-plugin`,afterLoadSnapshot(e){let t=e&&e.remoteSnapshot,n=t&&t.globalName,r=t&&t.version;if(!n||!r||!t.remoteEntry)return e;let i=globalThis.__FEDERATION__&&globalThis.__FEDERATION__.moduleInfo,a=n+`:`+r;return i&&!i[a]&&(i[a]=t),e}}}let me=q.sharedHandler.hooks.lifecycle.resolveShare,J=new WeakMap;me.on(e=>{var t;let n=(t=e.shareInfo)==null?void 0:t[W],r=e.resolver;return typeof r==`function`&&(e.resolver=(...e)=>{let t=r(...e),i=t==null?void 0:t.shared;return i&&(typeof i==`object`||typeof i==`function`)&&!J.has(i)&&J.set(i,{from:i.from}),n!==void 0&&i&&G.set(n,i),t}),e});let he=(e,t,n,r)=>{if(!e||e[t]!==n)return;let i=Object.assign({},r,{version:r.version??t,scope:r.scope??(n==null?void 0:n.scope)??[`default`],strategy:`loaded-first`}),a=r.from;e[t]=i;let o=()=>n===void 0?e[t]===void 0:e[t]===n;return{provider:i,reveal(){return e[t]===i&&(n===void 0?delete e[t]:e[t]=n,!0)},reapply(){return o()?(e[t]=i,!0):!1},release(s,c=!0){return r.from=a,e[t]===i?c?s?(i.from=a,s&&i.lib&&(i.loaded=!0),r.strategy===void 0?delete i.strategy:i.strategy=r.strategy,!0):(n===void 0?delete e[t]:e[t]=n,!1):(n===void 0?delete e[t]:e[t]=n,!0):!c&&o()}}},ge=e=>Object.entries(e||{}).map(([e,t])=>({provider:t,version:e,from:t.from,registered:!0})),_e=(e,t)=>{if(t===void 0)return;let n;for(let r of e){let e=r.provider,i=e.treeShaking||e;if(r.loadedFactory===t||e.lib===t||i.lib===t){if(n)return;n=r}}return n},ve=async(e,t,n)=>{let r=++de;K.set(r,{pinned:n});try{let n=await q.loadShare(e,{customShareInfo:{shareConfig:t,[W]:r}});return{factory:n===!1?void 0:n,selectedProvider:G.get(r)}}finally{G.delete(r),K.delete(r)}},ye=async(e,t,n,r,i,a,o=!0)=>{let s=a.from,c=he(n,r,i,a);if(!c)return;let l;try{l=await ve(e,t,c)}catch(e){throw c.release(!1),e}let u=l==null?void 0:l.factory;if(u===void 0){c.release(!1);return}let d=ge(n),f=c.provider.treeShaking||c.provider,p=c.provider.lib===u||f.lib===u;if(!o&&p){let e=d.findIndex(e=>e.provider===c.provider);e!==-1&&d.splice(e,1)}!o&&!d.some(e=>e.provider===a)&&d.push({provider:a,version:r,from:s,registered:!1,loadedFactory:p?u:void 0});let m=!o&&l.selectedProvider===c.provider&&p?a:l.selectedProvider;if(m&&!d.some(e=>e.provider===m)){let e=J.get(m),t=typeof m.version==`string`&&m.version?m.version:r;d.push({provider:m,version:t,from:e?e.from:m.from,registered:(n==null?void 0:n[t])===m,loadedFactory:u})}let h=d.find(e=>e.provider===m)??_e(d,u);if(!c.release(!0,(h==null?void 0:h.provider)===c.provider)||!h)return;let g=J.get(h.provider);h.from=h.provider===a?s:g?g.from:h.provider.from,g&&(h.provider.from=g.from);let _=typeof u==`function`?u():u,v=await Promise.resolve(_);if(!(h.registered&&(n==null?void 0:n[h.version])!==h.provider))return{provider:h.provider,selection:h,resolved:v}},Y=new Set,X=new Map,be=async(t,n,r)=>{var i;let a=!!((i=n.shareConfig)!=null&&i.singleton);if(!a&&n.canLiveRebind!==!1)try{var s,u;let i=C(r,t,n,`version-first`),d=x(r,i);if(!d||((s=n.shareConfig)==null?void 0:s.import)===!1&&w(i,n)||(i==null||(u=i.shareConfig)==null?void 0:u.import)===!1)return;let{version:f}=d;if(!a&&f!==n.version||!i.lib&&!i.loading&&!(i.loaded&&typeof i.get==`function`))return;let p=o(t,a,n.version,n.scope);if(c(l.share,p)!==void 0)return;let m=e[t],h=m==null?void 0:m[f];if(d.registered&&!w(h,i))return;let g,_=i.lib;if(!_&&V(i)||(!_&&i.loading&&(_=await i.loading),!_&&i.loaded&&typeof i.get==`function`&&(_=await i.get()),!_))return;let v=typeof _==`function`?_():_,y=await Promise.resolve(v),b=d.registered?h:i;g={provider:b,selection:{provider:b,version:f,from:i.from,registered:d.registered},resolved:y};let S=g==null?void 0:g.provider,E=g==null?void 0:g.selection;if(!E)return;let D=g==null?void 0:g.resolved;if(D===void 0||c(l.share,p)!==void 0||E.registered&&(m==null?void 0:m[E.version])!==S)return;T(l.share,p,ce(D),E.from),Y.add(S)}catch(e){console.error(`[Module Federation] Failed to bridge materialized shared module "`+t+`"`,e)}},xe=async(t,n,r,i,a)=>{try{var s,u,d,f;let m=o(t,(s=n.shareConfig)==null?void 0:s.singleton,n.version,n.scope),h=c(l.share,m),g=b(l.share,m),_=C(r,t,n,`version-first`),v=_||S(r,t,n,`version-first`)||n,y=x(r,v);if(!y)return;let D=w(v,n),{version:O}=y;if(!((u=n.shareConfig)!=null&&u.singleton)&&O!==n.version)return;let k=i==null?void 0:i[O],A=E(P,te,e,`default`,t,y,_,k,`version-first`);if(!A&&!D)return;let{provider:j,scopeRootProvider:ee}=A||{provider:v,scopeRootProvider:void 0};if(n.canLiveRebind===!1||((d=n.shareConfig)==null?void 0:d.import)===!1&&w(j,n)||(j==null||(f=j.shareConfig)==null?void 0:f.import)===!1||h!==void 0&&g!==p)return;let M=e[t],N=M==null?void 0:M[O];if(y.registered&&!ee&&!w(N,j))return;let F=await ye(t,n.shareConfig,M,O,N,j,y.registered&&!D),I=F==null?void 0:F.provider,L=F==null?void 0:F.selection;if(!L||w(I,n)||a&&(a.version!==L.version||!w({from:L.from},a.provider))||Y.has(I))return;let R=F==null?void 0:F.resolved;if(R===void 0)return;let ne=c(l.share,m),re=b(l.share,m);if(ne!==void 0&&re!==p||L.registered&&(M==null?void 0:M[L.version])!==I)return;a||X.set(t,{version:L.version,provider:{from:L.from}}),Y.add(I);let z=ce(R);T(l.share,m,z,L.from)}catch(e){console.error(`[Module Federation] Failed to bridge external shared module "`+t+`"`,e)}};for(let e of m)await Promise.all(e.map(async e=>{let t=B[e];t&&t.materialize!==!1&&!t.treeShaking&&await be(e,t,z[e])}));for(let[e,t]of Object.entries(B)){var Se;if(t.treeShaking)continue;let n=o(e,(Se=t.shareConfig)==null?void 0:Se.singleton,t.version,t.scope);if(c(l.share,n)!==void 0)continue;let r=o(e,!0,t.version,t.scope),i=c(l.share,r);i!==void 0&&T(l.share,n,i,b(l.share,r))}let Ce=[`react`,`prop-types`,`react/jsx-runtime`,`react-dom`,`react-dom/client`,`@mui/material`,`@iobroker/gui-components`],we=[[`react`,`prop-types`],[`react/jsx-runtime`,`react-dom`],[`react-dom/client`,`@mui/material`],[`@iobroker/gui-components`]],Z=new Map(Ce.map((e,t)=>[e,t])),Te={2:[0],3:[0],4:[0,3],5:[1,0,3],6:[0,3,5]},Q=Ce.filter(e=>{var t;return B[e]&&(B[e].materialize!==!1||((t=B[e].shareConfig)==null?void 0:t.import)===!1)});l.providerInit||=new Map;let Ee=(e,t)=>{let n=l.providerInit.get(e);if(n)return n;let r=Promise.resolve().then(t);return l.providerInit.set(e,r),r.catch(()=>l.providerInit.delete(e)),r};var De=async e=>{let t=new Set(e);for(let e of we)await Promise.all(e.filter(e=>t.has(e)).map(async e=>{var t,n;let r=B[e],i=o(e,(t=r.shareConfig)==null?void 0:t.singleton,r.version,r.scope);if(((n=r.shareConfig)==null?void 0:n.import)===!1||r.treeShaking||c(l.share,i)!==void 0)return;let a=o(e,!0,r.version,r.scope),s=c(l.share,a);if(s!==void 0){T(l.share,i,s,b(l.share,a));return}let u=typeof H==`function`?H(e,r):void 0;if(u){let e=u.lib;if(!e&&u.loading&&(e=await u.loading),!e&&u.loaded&&typeof u.get==`function`&&(e=await u.get()),e){let t=typeof e==`function`?e():e,n=await Promise.resolve(t);T(l.share,i,(e=>{let t=e;for(let e=0;e<5;e++){let e=t==null?void 0:t.default;if(!e||typeof e!=`object`||Object.keys(e).length===0)break;let n=Object.keys(t).filter(e=>e!=="default").map(e=>t[e]);if(n.length>0&&n.some(e=>e!==void 0))break;t=e}return t})(n),u.from)}return}let d=i.canonical,f=await Ee(d,async()=>{let e=await r.get(),t=typeof e==`function`?e():e;return Promise.resolve(t)}),m=(e=>{let t=e;for(let e=0;e<5;e++){let e=t==null?void 0:t.default;if(!e||typeof e!=`object`||Object.keys(e).length===0)break;let n=Object.keys(t).filter(e=>e!=="default").map(e=>t[e]);if(n.length>0&&n.some(e=>e!==void 0))break;t=e}return t})(f),h=m===f?{...f}:m;h.__esModule!==!0&&Object.defineProperty(h,"__esModule",{value:!0,enumerable:!1}),T(l.share,i,h,p)}))};let Oe=e=>{var t,n;let r=B[e];if(!r.treeShaking&&((t=r.shareConfig)==null?void 0:t.import)!==!1)return!1;let i=o(e,(n=r.shareConfig)==null?void 0:n.singleton,r.version,r.scope);return r.treeShaking?M(l.share,i,p)===void 0&&c(l.share,i)===void 0:c(l.share,i)===void 0},ke=e=>{var t,n;let r=B[e],i=o(e,(t=r.shareConfig)==null?void 0:t.singleton,r.version,r.scope);return(r.treeShaking?M(l.share,i,p)??c(l.share,i):c(l.share,i))===void 0?r.treeShaking||((n=r.shareConfig)==null?void 0:n.import)===!1?!0:typeof C==`function`&&!!C(z[e],e,r,`version-first`):!1},Ae=e=>{let t=!0;for(;t;){t=!1;for(let n of Q){let r=Z.get(n);e.has(r)||(Te[r]||[]).some(t=>e.has(t))&&(e.add(r),t=!0)}}return e},je=Ae(new Set(Q.filter(ke).map(e=>Z.get(e)))),Me=Q.filter(e=>!je.has(Z.get(e)));var Ne=Q.filter(e=>je.has(Z.get(e)));await De(Me);try{await _(async()=>{await Promise.all(await q.initializeSharing(`default`,{strategy:`version-first`,from:`build`,initScope:t}))})}catch(e){console.error(`[Module Federation]`,e)}re();let Pe=async()=>{for(let t of m)await Promise.all(t.map(async t=>{let n=B[t];n&&n.materialize!==!1&&!n.treeShaking&&await xe(t,n,e[t],z[t],void 0)}))};await Pe(),ae&&(g=Pe);try{var Fe;let e=(Fe=globalThis.__FEDERATION__)==null?void 0:Fe.__SHARE__,t=Object.create(null);if(e)for(let[,n]of Object.entries(e))for(let e of d){let r=n==null?void 0:n[e];if(r)for(let[e,n]of Object.entries(r)){let r=B==null?void 0:B[e],i=z[e],a=X.get(e);if(!r||!i||!a||r.treeShaking)continue;let o=t[e]||(t[e]=Object.create(null));for(let[e,t]of Object.entries(n)){if(!t.lib||a.version!==e||!w(t,a.provider))continue;let n=i[e];(t===n||n!=null&&n.from&&t.from===n.from)&&(t===r||r.from&&t.from===r.from||o[e]===void 0&&(o[e]=t))}}}for(let e of m)await Promise.all(e.map(async e=>{let n=t[e];n&&await xe(e,B[e],n,z[e],X.get(e))}))}catch(e){console.error(`[Module Federation] Failed to bridge external shared modules`,e)}let Ie=async()=>{},Le=async(t,n)=>{var r,i;let a=o(t,(r=n.shareConfig)==null?void 0:r.singleton,n.version,n.scope),s=n.treeShaking?M(l.share,a,p):c(l.share,a);if(((i=n.shareConfig)==null?void 0:i.import)!==!1||s!==void 0||se(t,n,z[t]))return;let u=e=>{let t=e;for(let e=0;e<5;e++){let e=t==null?void 0:t.default;if(!e||typeof e!=`object`||Object.keys(e).length===0)break;let n=Object.keys(t).filter(e=>e!=="default").map(e=>t[e]);if(n.length>0&&n.some(e=>e!==void 0))break;t=e}return t},d=e==null?void 0:e[t],f=S(d,t,n,`version-first`)||n,m=x(d,f);if(!m)return;let h=e=>{var t;return e===n||(e==null||(t=e.shareConfig)==null?void 0:t.import)===!1};if(h(f))return;let{version:g}=m,_=d==null?void 0:d[g],v=await ye(t,n.shareConfig,d,g,_,f,m.registered),y=v==null?void 0:v.selection,b=v==null?void 0:v.provider,C=v==null?void 0:v.resolved;if(!y||h(b)||C===void 0||(n.treeShaking?M(l.share,a,p):c(l.share,a))!==void 0||y.registered&&(d==null?void 0:d[y.version])!==b)return;let w=u(C);if(n.treeShaking){let e=n.treeShaking.providedExports??n.treeShaking.usedExports??[];A(l.share,a,e,w),N(l.share,a,p,w)}else T(l.share,a,w,y.from)},Re=[],$=new Set;for(let e of Ne){let t=B[e],n=Z.get(e);if(Oe(e))try{var ze;t.treeShaking?await Ie(e,t):((ze=t.shareConfig)==null?void 0:ze.import)===!1&&await Le(e,t)}catch(t){console.error(`[Module Federation] Failed to resolve runtime-only shared module "${e}"`,t)}Oe(e)&&$.add(n)}return Ae($),Re.push(...Ne.filter(e=>!$.has(Z.get(e)))),await De(Re),s(q),q}async function A(e){let t=await O();if(!(e in t))throw Error(`[Module Federation] Module ${e} does not exist in container.`);return g&&await g(),l.pendingShareLoads&&await Promise.all(l.pendingShareLoads),t[e]().then(e=>()=>e)}export{A as get,k as init};
1
+ import{t as e}from"./assets/vite-preload-helper-DjNwdemH.js";import{t}from"./assets/dist-CzitsFi7.js";import{t as n}from"./assets/helpers-BZgjFQNf.js";var r={};typeof __VUE_HMR_RUNTIME__>`u`&&(globalThis.__VUE_HMR_RUNTIME__={createRecord(){},rerender(){},reload(){}});var i=`__mf_init__virtual:mf:__mfe_internal__iobroker_javascript__mf_owner__234968779812303__mf_v__runtimeInit__mf_v__.js__`,a=globalThis[i];if(!a){let e,t,n=new Promise((n,r)=>{e=n,t=r});a=globalThis[i]={initPromise:n,initResolve:e,initReject:t}}var o=a.initResolve,s=`__mf_module_cache__`;globalThis[s]||={share:{},remote:{}},globalThis[s].share||={},globalThis[s].remote||={};var c=globalThis[s];for(let e of Object.keys(c.share))if(e.startsWith(`default:`)){let t=e.slice(8);c.share[t]===void 0&&(c.share[t]=c.share[e])}else if(!e.includes(`:`)){let t=`default:`+e;c.share[t]===void 0&&(c.share[t]=c.share[e])}var l={},u=Array.isArray(`default`)?`default`:[`default`],d=`default`,f=`iobroker_javascript`,p=[[`react`,`prop-types`],[`react/jsx-runtime`,`react-dom`],[`react-dom/client`,`@mui/material`],[`@iobroker/gui-components`]],m,h;async function g(e){for(let t=0;;t++)try{return await e()}catch(e){throw e}}var _=Symbol(`mf.originalSharedProvider`),v={emit:e=>e},y=e=>Array.isArray(e.scope)?e.scope:[e.scope||`default`],b=(e,t)=>{if(t!==`version-first`)return e;let n={};for(let[t,r]of Object.entries(e))n[t]=Object.assign({},r,{[_]:r});return n},x=(e,t)=>{if(!t)return;let n=Object.entries(e||{}),r=n.find(([,e])=>e===t);if(r)return{version:r[0],provider:t,registered:!0};if(typeof t.version==`string`&&t.version)return{version:t.version,provider:t,registered:!1};let i=n.filter(([,e])=>e===t||!!(t.from&&(e==null?void 0:e.from)===t.from));if(i.length===1)return{version:i[0][0],provider:t,registered:!1}},S=(e,t,r,i)=>{var a;if(!e||!r)return;let o=Object.fromEntries(Object.entries(e).filter(([,e])=>{var t;return(e==null||(t=e.shareConfig)==null?void 0:t.import)!==!1}));if(Object.keys(o).length===0)return;let s=y(r),c=b(o,i),l={};for(let e of s)l[e||`default`]={[t]:c};let u=(a=n.getRegisteredShare(l,t,{...r,scope:s,strategy:i},v))==null?void 0:a.shared;return(u==null?void 0:u[_])||u},C=(e,t,n,r)=>{var i;let a=e=>w(e,n),o=Object.fromEntries(Object.entries(e||{}).filter(([,e])=>{var t;return!a(e)&&(e==null||(t=e.shareConfig)==null?void 0:t.import)!==!1}));n!=null&&n.version&&((i=n.shareConfig)==null?void 0:i.import)!==!1&&(o[n.version]||(o[n.version]=n));let s=S(o,t,n,r);return a(s)?void 0:s},w=(e,t)=>e===t||!!(t!=null&&t.from&&(e==null?void 0:e.from)===t.from),T=(e,t,n,r,i,a,o,s,c)=>{var l,u;if(c!==`version-first`||!s)return;let d=t==null||(l=t.options)==null||(l=l.shared)==null?void 0:l[i],f=Array.isArray(d)?d.find(e=>(e==null?void 0:e.version)===a):void 0,p=((s==null?void 0:s.from)===(t==null||(u=t.options)==null?void 0:u.name)?s:void 0)||(w(f,s)?f:t?void 0:s);if(p)return e.some(e=>{var i,a;return e!==t&&(e==null||(i=e.options)==null?void 0:i.name)===(o==null?void 0:o.from)&&(e==null||(a=e.shareScopeMap)==null?void 0:a[r])===n})?p:void 0},E=(e,t,n,r,i,a,o,s,c)=>{let l=a.registered?T(e,t,n,r,i,a.version,a.provider,s,c):void 0,u=l||o;if(u&&(!a.registered||w(u,s)))return{provider:u,scopeRootProvider:l}};async function D(){return m||=g(()=>e(()=>import(`./assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-Ceh8EDcF.js`),[],import.meta.url)).catch(e=>{throw m=void 0,e}),m}async function O(){return r}async function k(e={},n=[],r={}){var i,s;let m=(e,t,n,r)=>{let i=(Array.isArray(r)?r[0]:r)||`default`,a=t||!n?e:e+`@`+n,o={canonical:i+`:`+a};return i==="default"&&(o.aliases=[a]),o},_=(e,t)=>{let n=e[t.canonical];if(n!==void 0)return n;let r=t.aliases||[];for(let n of r){if(!Object.prototype.hasOwnProperty.call(e,n))continue;let r=e[n];if(r!==void 0)return e[t.canonical]=r,r}},v=Symbol.for(`module-federation.shared-cache-listeners`),y=Symbol.for(`module-federation.shared-cache-owners`),b=e=>{let t=e[y];return t===void 0&&(t=Object.create(null),Object.defineProperty(e,y,{value:t,enumerable:!1,configurable:!1,writable:!1})),t},T=(e,t)=>{var n;return(n=e[y])==null?void 0:n[t.canonical]},O=e=>{let t=[e,e==null?void 0:e.default];for(let e of t)if(e&&typeof e==`object`){for(let t of[`__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE`,`__TEST_INTERNALS`,`__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED`]){let n=e[t];if(n&&typeof n==`object`)return{internals:n}}if(typeof e.useState==`function`)return{hook:e.useState}}},k=(e,t)=>{if(e===t)return!0;let n=O(e),r=O(t);if(!n||!r)return!1;let i=n.internals,a=r.internals;return i!==void 0||a!==void 0?i!==void 0&&i===a:typeof n.hook==`function`&&n.hook===r.hook},A=(e,t,n,r)=>{var i;let a=_(e,t);if(a!==void 0&&k(a,n))return n;e[t.canonical]=n;let o=t.aliases||[];for(let t of o)Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0});let s=e[y];r===void 0?s&&delete s[t.canonical]:b(e)[t.canonical]=r;let c=(i=e[v])==null?void 0:i[t.canonical];if(c)for(let e of c)e(n);return n},j=Symbol.for(`module-federation.tree-shaking-shared-cache`),ee=e=>{let t=e[j];return t===void 0&&(t=Object.create(null),Object.defineProperty(e,j,{value:t,enumerable:!1,configurable:!1,writable:!1})),t},M=(e,t,n,r)=>{if(!Array.isArray(n))return r;let i=[...new Set(n)].sort(),a=ee(e),o=a[t.canonical]||=[],s=o.find(e=>e.providedExports.length===i.length&&e.providedExports.every((e,t)=>e===i[t]));return s?s.value=r:o.push({providedExports:i,value:r}),r},N=Symbol.for(`module-federation.tree-shaking-shared-selection-cache`),P=e=>{let t=e[N];return t===void 0&&(t=Object.create(null),Object.defineProperty(e,N,{value:t,enumerable:!1,configurable:!1,writable:!1})),t},F=(e,t,n)=>{var r;let i=_(e,t);return i===void 0?(r=e[N])==null||(r=r[t.canonical])==null?void 0:r[n]:i},I=(e,t,n,r)=>{let i=P(e),a=i[t.canonical]||=Object.create(null);return a[n]=r,r},L=((i=globalThis.__FEDERATION__)==null?void 0:i.__INSTANCES__)||[],R=(s=n.find(e=>e==null?void 0:e.from))==null?void 0:s.from,te=L.find(t=>{var n,r;return(t==null||(n=t.options)==null?void 0:n.name)===R&&(t==null||(r=t.shareScopeMap)==null?void 0:r.default)===e})||L.find(t=>{var n,r;return(t==null||(n=t.options)==null?void 0:n.name)!==f&&(t==null||(r=t.shareScopeMap)==null?void 0:r.default)===e}),ne=Object.create(null),re=e=>{let t=Object.create(null);for(let[n,r]of Object.entries(e||{}))t[n]=Object.assign(Object.create(null),r);return t},ie=(e,t)=>{var n;for(let[i,a]of Object.entries(((n=q.shareScopeMap)==null?void 0:n[e])||{}))for(let[e,n]of Object.entries(a||{})){var r;if(!n||n.get===((r=B[i])==null?void 0:r.get))continue;let a=t[i]||={};a[e]===void 0&&(a[e]=n)}},ae=(e,t)=>{ie(e,t);let n=!te&&Object.values(t||{}).some(e=>Object.values(e||{}).some(V)),r=n?re(t):t;return ne[e]={host:t,runtime:r,isWebpackScope:n},r},oe=()=>{let e=Object.values(ne).filter(({isWebpackScope:e})=>e);if(e.length!==0)for(let{host:t,runtime:n}of e)for(let[e,r]of Object.entries(t||{})){let t=n[e]||=Object.create(null);for(let[e,n]of Object.entries(r||{}))t[e]=n}},z=Object.create(null);for(let[t,n]of Object.entries(e)){let e=z[t]=Object.create(null);for(let[t,r]of Object.entries(n))e[t]=Object.assign({},r)}let{usedShared:B,usedRemotes:se}=await D();function V(e){if(typeof(e==null?void 0:e.get)!=`function`)return!1;let t=Function.prototype.toString.call(e.get);return t.includes(`__webpack_require__`)||/\.\s*e\s*\([^)]*\)\s*\.then\s*\(/.test(t)}let ce=Object.values(z).some(e=>Object.values(e||{}).some(V)),le=e=>{let t=e.split(`/`);return e.startsWith(`@`)?t.slice(0,2).join(`/`):t[0]},H=(t,n,r,i)=>{if(typeof C!=`function`)return;let a=le(t),o=!i||a===t?[[t,n]]:[[t,n],[a,B[a]]];for(let[n,i]of o){if(!i)continue;let a=C(r?n===t?r:z[n]:z[n]??e[n],n,i,`version-first`);if(a)return a}},ue=(e,t,n)=>{let r=H(e,t,n,!0);return r&&V(r)&&!r.lib&&!r.loaded?r:void 0};var U=l[d];if(U||=l[d]={from:f},n.indexOf(U)>=0)return;n.push(U);let de=e=>{let t=e;for(let e=0;e<5;e++){let e=t==null?void 0:t.default;if(!e||typeof e!=`object`||Object.keys(e).length===0)break;let n=Object.getPrototypeOf(e);if(n!==null&&n!==Object.prototype)break;let r=Object.keys(t).filter(e=>e!=="default").map(e=>t[e]);if(r.length>0&&r.some(e=>e!==void 0))break;t=e}return t},fe=[],pe=globalThis.window===void 0?await Promise.all([]):[],W=`__mf_vite_runtime_share_load_id__`,me=0,G=new Map,K=new Map,q=t({name:f,remotes:se,shared:B,plugins:[he(),ge(),...fe,...pe],shareStrategy:`version-first`});q.initShareScopeMap(`default`,ae(`default`,e));function he(){return{name:`vite-share-pin-lifecycle-plugin`,resolveShare(e){var t;let n=(t=e.shareInfo)==null?void 0:t[W],r=n===void 0?void 0:K.get(n);if(!r)return e;let i=e.resolver;return e.resolver=(...e)=>(r.pinned.reapply(),i(...e)),r.pinned.reveal(),e}}}function ge(){return{name:`vite-real-name-snapshot-plugin`,afterLoadSnapshot(e){let t=e&&e.remoteSnapshot,n=t&&t.globalName,r=t&&t.version;if(!n||!r||!t.remoteEntry)return e;let i=globalThis.__FEDERATION__&&globalThis.__FEDERATION__.moduleInfo,a=n+`:`+r;return i&&!i[a]&&(i[a]=t),e}}}let _e=q.sharedHandler.hooks.lifecycle.resolveShare;if(!q.__mfKeepAdoptedProviders){var J,ve;q.__mfKeepAdoptedProviders=!0,(J=q.sharedHandler)==null||(J=J.hooks)==null||(J=J.lifecycle)==null||(J=J.afterRegisterShare)==null||(ve=J.on)==null||ve.call(J,e=>{var t,n,r;let{shared:i,previousShared:a,registeredShared:o}=e||{};if((i==null||(t=i.shareConfig)==null?void 0:t.import)!==!1||o!==i||!a||((n=a.shareConfig)==null?void 0:n.import)===!1)return;let s=(r=q.shareScopeMap)==null||(r=r[e.scope])==null?void 0:r[e.pkgName];s&&s[i.version]===i&&(s[i.version]=a)})}let Y=new WeakMap;_e.on(e=>{var t;let n=(t=e.shareInfo)==null?void 0:t[W],r=e.resolver;return typeof r==`function`&&(e.resolver=(...t)=>{var i;let a=r(...t);if((a==null||(i=a.shared)==null||(i=i.shareConfig)==null?void 0:i.import)===!1&&typeof S==`function`&&B[e.pkgName]){var o,s;let t=S((o=e.shareScopeMap)==null||(o=o[e.scope])==null?void 0:o[e.pkgName],e.pkgName,B[e.pkgName],`version-first`);t&&((s=t.shareConfig)==null?void 0:s.import)!==!1&&(a={shared:t,useTreesShaking:a.useTreesShaking})}let c=a==null?void 0:a.shared;return c&&(typeof c==`object`||typeof c==`function`)&&!Y.has(c)&&Y.set(c,{from:c.from}),n!==void 0&&c&&G.set(n,c),a}),e});let ye=(e,t,n,r)=>{if(!e||e[t]!==n)return;let i=Object.assign({},r,{version:r.version??t,scope:r.scope??(n==null?void 0:n.scope)??[`default`],strategy:`loaded-first`}),a=r.from;e[t]=i;let o=()=>n===void 0?e[t]===void 0:e[t]===n;return{provider:i,reveal(){return e[t]===i&&(n===void 0?delete e[t]:e[t]=n,!0)},reapply(){return o()?(e[t]=i,!0):!1},release(s,c=!0){return r.from=a,e[t]===i?c?s?(i.from=a,s&&i.lib&&(i.loaded=!0),r.strategy===void 0?delete i.strategy:i.strategy=r.strategy,!0):(n===void 0?delete e[t]:e[t]=n,!1):(n===void 0?delete e[t]:e[t]=n,!0):!c&&o()}}},be=e=>Object.entries(e||{}).map(([e,t])=>({provider:t,version:e,from:t.from,registered:!0})),xe=(e,t)=>{if(t===void 0)return;let n;for(let r of e){let e=r.provider,i=e.treeShaking||e;if(r.loadedFactory===t||e.lib===t||i.lib===t){if(n)return;n=r}}return n},Se=async(e,t,n)=>{let r=++me;K.set(r,{pinned:n});try{let n=await q.loadShare(e,{customShareInfo:{shareConfig:t,[W]:r}});return{factory:n===!1?void 0:n,selectedProvider:G.get(r)}}finally{G.delete(r),K.delete(r)}},Ce=async(e,t,n,r,i,a,o=!0)=>{let s=a.from,c=ye(n,r,i,a);if(!c)return;let l;try{l=await Se(e,t,c)}catch(e){throw c.release(!1),e}let u=l==null?void 0:l.factory;if(u===void 0){c.release(!1);return}let d=be(n),f=c.provider.treeShaking||c.provider,p=c.provider.lib===u||f.lib===u;if(!o&&p){let e=d.findIndex(e=>e.provider===c.provider);e!==-1&&d.splice(e,1)}!o&&!d.some(e=>e.provider===a)&&d.push({provider:a,version:r,from:s,registered:!1,loadedFactory:p?u:void 0});let m=!o&&l.selectedProvider===c.provider&&p?a:l.selectedProvider;if(m&&!d.some(e=>e.provider===m)){let e=Y.get(m),t=typeof m.version==`string`&&m.version?m.version:r;d.push({provider:m,version:t,from:e?e.from:m.from,registered:(n==null?void 0:n[t])===m,loadedFactory:u})}let h=d.find(e=>e.provider===m)??xe(d,u);if(!c.release(!0,(h==null?void 0:h.provider)===c.provider)||!h)return;let g=Y.get(h.provider);h.from=h.provider===a?s:g?g.from:h.provider.from,g&&(h.provider.from=g.from);let _=typeof u==`function`?u():u,v=await Promise.resolve(_);if(!(h.registered&&(n==null?void 0:n[h.version])!==h.provider))return{provider:h.provider,selection:h,resolved:v}},X=new Set,we=new Map,Te=async(t,n,r)=>{var i;let a=!!((i=n.shareConfig)!=null&&i.singleton);if(!a&&n.canLiveRebind!==!1)try{var o,s;let i=C(r,t,n,`version-first`),l=x(r,i);if(!l||((o=n.shareConfig)==null?void 0:o.import)===!1&&w(i,n)||(i==null||(s=i.shareConfig)==null?void 0:s.import)===!1)return;let{version:u}=l;if(!a&&u!==n.version||!i.lib&&!i.loading&&!(i.loaded&&typeof i.get==`function`))return;let d=m(t,a,n.version,n.scope);if(_(c.share,d)!==void 0)return;let f=e[t],p=f==null?void 0:f[u];if(l.registered&&!w(p,i))return;let h,g=i.lib;if(!g&&V(i)||(!g&&i.loading&&(g=await i.loading),!g&&i.loaded&&typeof i.get==`function`&&(g=await i.get()),!g))return;let v=typeof g==`function`?g():g,y=await Promise.resolve(v),b=l.registered?p:i;h={provider:b,selection:{provider:b,version:u,from:i.from,registered:l.registered},resolved:y};let S=h==null?void 0:h.provider,T=h==null?void 0:h.selection;if(!T)return;let E=h==null?void 0:h.resolved;if(E===void 0||_(c.share,d)!==void 0||T.registered&&(f==null?void 0:f[T.version])!==S)return;A(c.share,d,de(E),T.from),X.add(S)}catch(e){console.error(`[Module Federation] Failed to bridge materialized shared module "`+t+`"`,e)}},Ee=async(t,n,r,i,a)=>{try{var o,s,l,u;let d=m(t,(o=n.shareConfig)==null?void 0:o.singleton,n.version,n.scope),p=_(c.share,d),h=T(c.share,d),g=C(r,t,n,`version-first`),v=g||S(r,t,n,`version-first`)||n,y=x(r,v);if(!y)return;let b=w(v,n),{version:D}=y;if(!((s=n.shareConfig)!=null&&s.singleton)&&D!==n.version)return;let O=i==null?void 0:i[D],k=E(L,te,e,`default`,t,y,g,O,`version-first`);if(!k&&!b)return;let{provider:j,scopeRootProvider:ee}=k||{provider:v,scopeRootProvider:void 0};if(n.canLiveRebind===!1||((l=n.shareConfig)==null?void 0:l.import)===!1&&w(j,n)||(j==null||(u=j.shareConfig)==null?void 0:u.import)===!1||p!==void 0&&h!==f)return;let M=e[t],N=M==null?void 0:M[D];if(y.registered&&!ee&&!w(N,j))return;let P=await Ce(t,n.shareConfig,M,D,N,j,y.registered&&!b),F=P==null?void 0:P.provider,I=P==null?void 0:P.selection;if(!I||w(F,n)||a&&(a.version!==I.version||!w({from:I.from},a.provider))||X.has(F))return;let R=P==null?void 0:P.resolved;if(R===void 0)return;let ne=_(c.share,d),re=T(c.share,d);if(ne!==void 0&&re!==f||I.registered&&(M==null?void 0:M[I.version])!==F)return;a||we.set(t,{version:I.version,provider:{from:I.from}}),X.add(F);let ie=de(R);A(c.share,d,ie,I.from)}catch(e){console.error(`[Module Federation] Failed to bridge external shared module "`+t+`"`,e)}};for(let e of p)await Promise.all(e.map(async e=>{let t=B[e];t&&t.materialize!==!1&&!t.treeShaking&&await Te(e,t,z[e])}));for(let[e,t]of Object.entries(B)){var De;if(t.treeShaking)continue;let n=m(e,(De=t.shareConfig)==null?void 0:De.singleton,t.version,t.scope);if(_(c.share,n)!==void 0)continue;let r=m(e,!0,t.version,t.scope),i=_(c.share,r);i!==void 0&&A(c.share,n,i,T(c.share,r))}let Oe=[`react`,`prop-types`,`react/jsx-runtime`,`react-dom`,`react-dom/client`,`@mui/material`,`@iobroker/gui-components`],ke=[[`react`,`prop-types`],[`react/jsx-runtime`,`react-dom`],[`react-dom/client`,`@mui/material`],[`@iobroker/gui-components`]],Z=new Map(Oe.map((e,t)=>[e,t])),Ae={2:[0],3:[0],4:[0,3],5:[1,0,3],6:[0,3,5]},Q=Oe.filter(e=>{var t;return B[e]&&(B[e].materialize!==!1||((t=B[e].shareConfig)==null?void 0:t.import)===!1&&!B[e].lazy)});c.providerInit||=new Map;let je=(e,t)=>{let n=c.providerInit.get(e);if(n)return n;let r=Promise.resolve().then(t);return c.providerInit.set(e,r),r.catch(()=>c.providerInit.delete(e)),r};var Me=async e=>{let t=new Set(e);for(let e of ke)await Promise.all(e.filter(e=>t.has(e)).map(async e=>{var t,n,r;let i=B[e],a=m(e,(t=i.shareConfig)==null?void 0:t.singleton,i.version,i.scope);if(((n=i.shareConfig)==null?void 0:n.import)===!1||i.treeShaking||_(c.share,a)!==void 0)return;let o=m(e,!0,i.version,i.scope),s=_(c.share,o);if(s!==void 0){A(c.share,a,s,T(c.share,o));return}let l=typeof H==`function`?H(e,i):void 0;if(l){let e=l.lib;if(!e&&l.loading&&(e=await l.loading),!e&&l.loaded&&typeof l.get==`function`&&(e=await l.get()),e){let t=typeof e==`function`?e():e,n=await Promise.resolve(t);A(c.share,a,(e=>{let t=e;for(let e=0;e<5;e++){let e=t==null?void 0:t.default;if(!e||typeof e!=`object`||Object.keys(e).length===0)break;let n=Object.getPrototypeOf(e);if(n!==null&&n!==Object.prototype)break;let r=Object.keys(t).filter(e=>e!=="default").map(e=>t[e]);if(r.length>0&&r.some(e=>e!==void 0))break;t=e}return t})(n),l.from);return}if(typeof V==`function`&&V(l))return}let u=a.canonical,d=await je(u,async()=>{let e=await i.get(),t=typeof e==`function`?e():e;return Promise.resolve(t)});for(let t of((r=q.options.shared)==null?void 0:r[e])||[])t.get===i.get&&(t.eager=!0);let p=(e=>{let t=e;for(let e=0;e<5;e++){let e=t==null?void 0:t.default;if(!e||typeof e!=`object`||Object.keys(e).length===0)break;let n=Object.getPrototypeOf(e);if(n!==null&&n!==Object.prototype)break;let r=Object.keys(t).filter(e=>e!=="default").map(e=>t[e]);if(r.length>0&&r.some(e=>e!==void 0))break;t=e}return t})(d),h=p===d?{...d}:p;h.__esModule!==!0&&Object.defineProperty(h,"__esModule",{value:!0,enumerable:!1}),A(c.share,a,h,f)}))};let $=e=>{var t,n;let r=B[e];if(!r.treeShaking&&((t=r.shareConfig)==null?void 0:t.import)!==!1)return!1;let i=m(e,(n=r.shareConfig)==null?void 0:n.singleton,r.version,r.scope);return r.treeShaking?F(c.share,i,f)===void 0&&_(c.share,i)===void 0:_(c.share,i)===void 0},Ne=e=>{var t,n;let r=B[e],i=m(e,(t=r.shareConfig)==null?void 0:t.singleton,r.version,r.scope);return(r.treeShaking?F(c.share,i,f)??_(c.share,i):_(c.share,i))===void 0?r.treeShaking||((n=r.shareConfig)==null?void 0:n.import)===!1?!0:typeof C==`function`&&!!C(z[e],e,r,`version-first`):!1},Pe=e=>{let t=!0;for(;t;){t=!1;for(let n of Q){let r=Z.get(n);e.has(r)||(Ae[r]||[]).some(t=>e.has(t))&&(e.add(r),t=!0)}}return e},Fe=Pe(new Set(Q.filter(Ne).map(e=>Z.get(e)))),Ie=Q.filter(e=>!Fe.has(Z.get(e)));var Le=Q.filter(e=>Fe.has(Z.get(e)));await Me(Ie);try{await g(async()=>{await Promise.all(await q.initializeSharing(`default`,{strategy:`version-first`,from:`build`,initScope:n}))})}catch(e){console.error(`[Module Federation]`,e)}oe();let Re=async()=>{for(let t of p)await Promise.all(t.map(async t=>{let n=B[t];n&&n.materialize!==!1&&!n.treeShaking&&await Ee(t,n,e[t],z[t],void 0)}))};ce?h=Re:await Re();try{var ze;let e=(ze=globalThis.__FEDERATION__)==null?void 0:ze.__SHARE__,t=Object.create(null);if(e)for(let[,n]of Object.entries(e))for(let e of u){let r=n==null?void 0:n[e];if(r)for(let[e,n]of Object.entries(r)){let r=B==null?void 0:B[e],i=z[e],a=we.get(e);if(!r||!i||!a||r.treeShaking)continue;let o=t[e]||(t[e]=Object.create(null));for(let[e,t]of Object.entries(n)){if(!t.lib||a.version!==e||!w(t,a.provider))continue;let n=i[e];(t===n||n!=null&&n.from&&t.from===n.from)&&(t===r||r.from&&t.from===r.from||o[e]===void 0&&(o[e]=t))}}}for(let e of p)await Promise.all(e.map(async e=>{let n=t[e];n&&await Ee(e,B[e],n,z[e],we.get(e))}))}catch(e){console.error(`[Module Federation] Failed to bridge external shared modules`,e)}let Be=async()=>{},Ve=async(t,n)=>{var r,i;let a=m(t,(r=n.shareConfig)==null?void 0:r.singleton,n.version,n.scope),o=n.treeShaking?F(c.share,a,f):_(c.share,a);if(((i=n.shareConfig)==null?void 0:i.import)!==!1||o!==void 0||ue(t,n,z[t]))return;let s=e=>{let t=e;for(let e=0;e<5;e++){let e=t==null?void 0:t.default;if(!e||typeof e!=`object`||Object.keys(e).length===0)break;let n=Object.getPrototypeOf(e);if(n!==null&&n!==Object.prototype)break;let r=Object.keys(t).filter(e=>e!=="default").map(e=>t[e]);if(r.length>0&&r.some(e=>e!==void 0))break;t=e}return t},l=e==null?void 0:e[t],u=S(l,t,n,`version-first`)||n,d=x(l,u);if(!d)return;let p=e=>{var t;return e===n||(e==null||(t=e.shareConfig)==null?void 0:t.import)===!1};if(p(u))return;let{version:h}=d,g=l==null?void 0:l[h],v=await Ce(t,n.shareConfig,l,h,g,u,d.registered),y=v==null?void 0:v.selection,b=v==null?void 0:v.provider,C=v==null?void 0:v.resolved;if(!y||p(b)||C===void 0||(n.treeShaking?F(c.share,a,f):_(c.share,a))!==void 0||y.registered&&(l==null?void 0:l[y.version])!==b)return;let w=s(C);if(n.treeShaking){let e=n.treeShaking.providedExports??n.treeShaking.usedExports??[];M(c.share,a,e,w),I(c.share,a,f,w)}else A(c.share,a,w,y.from)},He=[],Ue=new Set;for(let e of Le){let t=B[e],n=Z.get(e);if($(e))try{var We;t.treeShaking?await Be(e,t):((We=t.shareConfig)==null?void 0:We.import)===!1&&await Ve(e,t)}catch(t){console.error(`[Module Federation] Failed to resolve runtime-only shared module "${e}"`,t)}$(e)&&Ue.add(n)}Pe(Ue),He.push(...Le.filter(e=>!Ue.has(Z.get(e)))),await Me(He);let Ge=new Map;return a.loadLazyShares=async t=>{let n=new Set(t);for(let t of p)await Promise.all(t.filter(e=>n.has(e)).map(t=>{let n=B[t];if(!n||!n.lazy||!$(t))return;let r=Ge.get(t);return r||(r=Ee(t,n,e[t],z[t],void 0).then(()=>$(t)?Ve(t,n):void 0),r.catch(()=>Ge.delete(t)),Ge.set(t,r)),r}))},o(q),q}async function A(e){let t=await O();if(!(e in t))throw Error(`[Module Federation] Module ${e} does not exist in container.`);return h&&await h(),c.pendingShareLoads&&await Promise.all(c.pendingShareLoads),t[e]().then(e=>()=>e)}export{A as get,k as init};
2
2
  if (typeof document !== 'undefined' && document.head) {
3
3
  try {
4
- for (const __mfWarmupPath of ["assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-CM95r358.js","assets/vite-preload-helper-CaC3yEL3.js","assets/dist-D4uJqRBO.js"]) {
4
+ for (const __mfWarmupPath of ["assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-Ceh8EDcF.js","assets/vite-preload-helper-DjNwdemH.js","assets/dist-CzitsFi7.js","assets/utils-DUKzLJUz.js"]) {
5
5
  const __mfWarmupLink = document.createElement('link');
6
6
  __mfWarmupLink.rel = 'modulepreload';
7
7
  __mfWarmupLink.crossOrigin = '';
package/admin/tab.html CHANGED
@@ -27,12 +27,9 @@
27
27
 
28
28
  <script type="text/javascript" onerror="setTimeout(function(){window.location.reload()}, 5000)" src="./../../lib/js/socket.io.js"></script>
29
29
  <title>Scripts</title>
30
- <script type="module" crossorigin src="./assets/mf-entry-bootstrap-0-a5a39621.js"></script>
31
- <link rel="modulepreload" crossorigin href="./assets/Import-Cu02ceLW.js">
32
- <link rel="modulepreload" crossorigin href="./assets/Error-DZ4vCykD.js">
33
- <link rel="modulepreload" crossorigin href="./assets/blockly-fcfyKYzp.js">
34
- <link rel="stylesheet" crossorigin href="./assets/index-CXaeqPRy.css">
35
- <link rel="modulepreload" crossorigin href="./assets/hostInit-CVybS7BB.js"><link rel="modulepreload" crossorigin href="./assets/index-B3s0zmWC.js"><link rel="modulepreload" crossorigin href="./remoteEntry.js"><link rel="modulepreload" crossorigin href="./assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-CM95r358.js"><link rel="modulepreload" crossorigin href="./assets/vite-preload-helper-CaC3yEL3.js"><link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-C0FnF6B9.js"><link rel="modulepreload" crossorigin href="./assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BEpNZh4U.js"><link rel="modulepreload" crossorigin href="./assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__180366418666083__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-FeM77flT.js"><link rel="modulepreload" crossorigin href="./assets/dist-D4uJqRBO.js"></head>
30
+ <script type="module" crossorigin src="./assets/mf-entry-bootstrap-0-6db6c4fc.js"></script>
31
+ <link rel="stylesheet" crossorigin href="./assets/index-BHhhebRG.css">
32
+ <link rel="modulepreload" crossorigin href="./assets/hostInit-CrHjJGJJ.js"><link rel="modulepreload" crossorigin href="./assets/index-Bmmscq2G.js"><link rel="modulepreload" crossorigin href="./remoteEntry.js"><link rel="modulepreload" crossorigin href="./assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-Ceh8EDcF.js"><link rel="modulepreload" crossorigin href="./assets/vite-preload-helper-DjNwdemH.js"><link rel="modulepreload" crossorigin href="./assets/helpers-BZgjFQNf.js"><link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-C0FnF6B9.js"><link rel="modulepreload" crossorigin href="./assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__234968779812303__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BRdHvuuG.js"><link rel="modulepreload" crossorigin href="./assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__234968779812303__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-DLWT3PGo.js"><link rel="modulepreload" crossorigin href="./assets/dist-CzitsFi7.js"><link rel="modulepreload" crossorigin href="./assets/utils-DUKzLJUz.js"></head>
36
33
  <body>
37
34
  <noscript> You need to enable JavaScript to run this app. </noscript>
38
35
  <script>
@@ -486,6 +483,5 @@
486
483
  custom="PROCEDURE"
487
484
  ></category>
488
485
  </xml>
489
- <script type="text/javascript" src="vs/loader.js"></script><script type="text/javascript" src="vs/configure.js"></script>
490
486
  </body>
491
487
  </html>
@@ -10,12 +10,16 @@
10
10
  * These functions are extracted so they can be unit-tested in isolation.
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.MAX_AI_REQUEST_TIMEOUT_MS = exports.PROVIDER_CREDENTIAL_ID_FIELD = exports.PROVIDER_KEY_FIELD = void 0;
13
+ exports.MAX_AI_MAX_TOKENS = exports.DEFAULT_AI_MAX_TOKENS = exports.MAX_AI_REQUEST_TIMEOUT_MS = exports.PROVIDER_CREDENTIAL_ID_FIELD = exports.PROVIDER_KEY_FIELD = void 0;
14
14
  exports.getProviderCredentialId = getProviderCredentialId;
15
15
  exports.resolveProviderCredentials = resolveProviderCredentials;
16
+ exports.resolveTestEndpoint = resolveTestEndpoint;
16
17
  exports.resolveRequestTimeout = resolveRequestTimeout;
17
18
  exports.resolveTestCredentials = resolveTestCredentials;
18
19
  exports.listAvailableProviders = listAvailableProviders;
20
+ exports.extractAiResponseInfo = extractAiResponseInfo;
21
+ exports.describeEmptyAiResponse = describeEmptyAiResponse;
22
+ exports.resolveMaxTokens = resolveMaxTokens;
19
23
  /** Maps each provider to the adapter-config field holding its API key. */
20
24
  exports.PROVIDER_KEY_FIELD = {
21
25
  openai: 'gptKey',
@@ -46,34 +50,52 @@ function getProviderCredentialId(config, provider) {
46
50
  }
47
51
  /**
48
52
  * Resolve API key and base URL for a provider from adapter config.
49
- * Optional `messageBaseUrl` takes precedence over the stored `gptBaseUrl`
50
- * (used by the settings-dialog Test button where the user's form value
51
- * should win over the persisted value).
53
+ *
54
+ * Both come from the configuration and from nowhere else - above all not from the message that asked
55
+ * for them. The key that is resolved here travels with the request as its authorisation, so a caller
56
+ * who could name the address could have this instance carry the key to one of their own. An address
57
+ * out of a message used to win over the stored one, which was the comfortable way to put a proxy in
58
+ * front of OpenAI; a proxy belongs in the configuration now, entered once by whoever may configure
59
+ * this instance. The test button of the settings dialog is the one exception - see
60
+ * {@link resolveTestEndpoint}.
61
+ *
62
+ * The stored `gptBaseUrl` belongs to the `custom` provider and to no other. `openai` used to inherit
63
+ * it, which sent every request meant for api.openai.com - and the OpenAI key with it - to whatever
64
+ * host the custom endpoint pointed at (#2369).
52
65
  */
53
- function resolveProviderCredentials(config, provider, messageBaseUrl) {
66
+ function resolveProviderCredentials(config, provider) {
54
67
  const cfg = config || {};
55
68
  const keyField = exports.PROVIDER_KEY_FIELD[provider];
56
69
  const apiKey = keyField ? (cfg[keyField] || '').toString().trim() : '';
57
- /*
58
- * The stored `gptBaseUrl` belongs to the `custom` provider and to no other. `openai` used to
59
- * inherit it, which sent every request meant for api.openai.com - and the OpenAI key with it -
60
- * to whatever host the custom endpoint pointed at, with no way to opt out: an empty
61
- * `messageBaseUrl` counts as "not provided" and fell back to the stored value again (#2369).
62
- *
63
- * `openai` still honours an *explicit* `messageBaseUrl`, which is the escape hatch for a proxy
64
- * in front of OpenAI, but it no longer inherits the custom endpoint of another provider.
65
- */
66
- let baseUrl = '';
67
- if (provider === 'custom') {
68
- // An empty/whitespace messageBaseUrl counts as "not provided" and falls back to the stored
69
- // value, so the frontend can safely send `baseUrl: ''` without losing the configured URL.
70
- baseUrl = (messageBaseUrl || cfg.gptBaseUrl || '').toString().trim();
71
- }
72
- else if (provider === 'openai') {
73
- baseUrl = (messageBaseUrl || '').toString().trim();
74
- }
70
+ const baseUrl = provider === 'custom' ? (cfg.gptBaseUrl || '').toString().trim() : '';
75
71
  return { apiKey, baseUrl };
76
72
  }
73
+ /**
74
+ * The address the Test button of the settings dialog may try.
75
+ *
76
+ * The dialog tests what stands in the form rather than what was saved, because the first thing
77
+ * anybody does is type a key and press it. The one thing it must not do is make this instance carry a
78
+ * secret of its own to an address that came with the message, so an address out of the form counts
79
+ * only together with a key out of the form: one's own key to one's own endpoint gives nothing away.
80
+ * As soon as the key comes from this system - from the configuration or from the credential store -
81
+ * the address comes from there too. And only the OpenAI-compatible provider has an address to try;
82
+ * the form has no field for one anywhere else.
83
+ *
84
+ * @param config the adapter configuration
85
+ * @param provider the provider that is being tested
86
+ * @param form what the Test button sent
87
+ * @param form.apiKey the key that stands in the form, if any
88
+ * @param form.baseUrl the address that stands in the form, if any
89
+ */
90
+ function resolveTestEndpoint(config, provider, form) {
91
+ const stored = resolveProviderCredentials(config, provider).baseUrl;
92
+ const formKey = (form.apiKey || '').toString().trim();
93
+ const formUrl = (form.baseUrl || '').toString().trim();
94
+ if (provider !== 'custom' || !formKey || !formUrl) {
95
+ return stored;
96
+ }
97
+ return formUrl;
98
+ }
77
99
  /** Ceiling for an AI request, and the budget when the caller names none */
78
100
  exports.MAX_AI_REQUEST_TIMEOUT_MS = 600_000;
79
101
  /**
@@ -99,11 +121,12 @@ function resolveRequestTimeout(messageTimeout) {
99
121
  * (settings-dialog form value), use it; otherwise fall back to the stored key.
100
122
  */
101
123
  function resolveTestCredentials(config, provider, messageApiKey, messageBaseUrl) {
102
- const fallback = resolveProviderCredentials(config, provider, messageBaseUrl);
124
+ const fallback = resolveProviderCredentials(config, provider);
103
125
  const explicitKey = (messageApiKey || '').toString().trim();
104
126
  return {
105
127
  apiKey: explicitKey || fallback.apiKey,
106
- baseUrl: fallback.baseUrl,
128
+ // only together with a key of the form, and only for the endpoint of one's own
129
+ baseUrl: resolveTestEndpoint(config, provider, { apiKey: explicitKey, baseUrl: messageBaseUrl }),
107
130
  };
108
131
  }
109
132
  /**
@@ -137,4 +160,101 @@ function listAvailableProviders(config) {
137
160
  }
138
161
  return providers;
139
162
  }
163
+ function toCount(value) {
164
+ return typeof value === 'number' && isFinite(value) ? value : undefined;
165
+ }
166
+ /**
167
+ * Pull the "why did it stop" fields out of a chat-completion response.
168
+ *
169
+ * Anthropic and the OpenAI-compatible endpoints spell both the reason and the token counts
170
+ * differently. The adapter normalizes them and passes them on to the editor, so an answer that
171
+ * was cut off or filtered can say so instead of arriving as an empty chat bubble.
172
+ */
173
+ function extractAiResponseInfo(parsed) {
174
+ const info = {};
175
+ const reason = parsed?.stop_reason ?? parsed?.choices?.[0]?.finish_reason;
176
+ if (typeof reason === 'string' && reason) {
177
+ info.finishReason = reason;
178
+ }
179
+ const input = toCount(parsed?.usage?.input_tokens ?? parsed?.usage?.prompt_tokens);
180
+ const output = toCount(parsed?.usage?.output_tokens ?? parsed?.usage?.completion_tokens);
181
+ if (input !== undefined || output !== undefined) {
182
+ info.usage = {
183
+ ...(input !== undefined ? { input } : {}),
184
+ ...(output !== undefined ? { output } : {}),
185
+ };
186
+ }
187
+ return info;
188
+ }
189
+ /**
190
+ * Why a 200 OK answer carried neither text nor a tool call.
191
+ *
192
+ * "Empty response from API" is true but useless - it sends the user looking for a broken key
193
+ * when the usual cause is a model that spent its whole output budget on reasoning tokens. The
194
+ * endpoint nearly always says why it stopped, so repeat that, and append a slice of the raw
195
+ * body for the cases where it does not.
196
+ *
197
+ * @param info the normalized stop reason and token counts
198
+ * @param rawBody the response body as it came off the wire
199
+ */
200
+ function describeEmptyAiResponse(info, rawBody) {
201
+ let why;
202
+ switch (info.finishReason) {
203
+ case 'max_tokens':
204
+ case 'length':
205
+ why = 'the model used up its output budget before writing an answer';
206
+ break;
207
+ case 'content_filter':
208
+ case 'refusal':
209
+ why = 'the endpoint filtered the answer away';
210
+ break;
211
+ case 'tool_use':
212
+ case 'tool_calls':
213
+ why = 'the model wanted to call a tool, but the answer carried no readable tool call';
214
+ break;
215
+ default:
216
+ why = info.finishReason ? `the endpoint stopped with "${info.finishReason}"` : '';
217
+ break;
218
+ }
219
+ const details = [];
220
+ if (info.finishReason) {
221
+ details.push(`stop reason: ${info.finishReason}`);
222
+ }
223
+ if (info.usage?.input !== undefined || info.usage?.output !== undefined) {
224
+ details.push(`tokens in/out: ${info.usage?.input ?? '?'}/${info.usage?.output ?? '?'}`);
225
+ }
226
+ let message = 'The API answered without any content';
227
+ if (why) {
228
+ message += ` - ${why}`;
229
+ }
230
+ if (details.length) {
231
+ message += ` (${details.join(', ')})`;
232
+ }
233
+ // Only worth showing when the endpoint told us nothing usable at all
234
+ if (!info.finishReason && rawBody) {
235
+ message += `. Response: ${rawBody.substring(0, 200)}`;
236
+ }
237
+ return message;
238
+ }
239
+ /** What Anthropic gets as `max_tokens` when the setting is empty or unusable */
240
+ exports.DEFAULT_AI_MAX_TOKENS = 8192;
241
+ /** Highest `max_tokens` the setting may ask for - beyond this every current model answers 400 */
242
+ exports.MAX_AI_MAX_TOKENS = 200_000;
243
+ /**
244
+ * The output budget for an Anthropic request.
245
+ *
246
+ * Anthropic insists on `max_tokens`, so there is no "let the endpoint decide". Too small and a
247
+ * generated script is cut off mid-line; too large and the model rejects the request outright, so
248
+ * the configured value is clamped into a range every model can live with.
249
+ *
250
+ * @param configured the value from the adapter settings
251
+ */
252
+ function resolveMaxTokens(configured) {
253
+ const requested = parseInt(configured, 10);
254
+ if (isNaN(requested) || requested <= 0) {
255
+ return exports.DEFAULT_AI_MAX_TOKENS;
256
+ }
257
+ // 1024 is the floor: below that not even a short answer with its reasoning fits
258
+ return Math.min(Math.max(requested, 1024), exports.MAX_AI_MAX_TOKENS);
259
+ }
140
260
  //# sourceMappingURL=aiProviderResolver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"aiProviderResolver.js","sourceRoot":"","sources":["../../src/lib/aiProviderResolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Helpers for resolving AI provider credentials in sendTo handlers.\n *\n * Keys are stored as `encryptedNative` + `protectedNative` in io-package.json —\n * they are never sent from the frontend. The backend looks them up in `this.config`\n * based on the `provider` name sent along with each `chatCompletion` or\n * `testApiConnection` request.\n *\n * These functions are extracted so they can be unit-tested in isolation.\n */\n\n/** Configuration subset that carries AI credentials. */\nexport interface AiConfigSlice {\n gptKey?: string;\n gptBaseUrl?: string;\n gptBaseUrlKey?: string;\n claudeKey?: string;\n geminiKey?: string;\n deepseekKey?: string;\n /**\n * Where the API keys come from:\n * - `manual`: keys are stored directly in the adapter config (encryptedNative)\n * - `manager`: the config only stores the ID of a credential in the central\n * ioBroker credential store (`system.credentials.*`), resolved at runtime\n */\n credentialType?: 'manual' | 'manager';\n credentialIdGptKey?: string;\n credentialIdClaudeKey?: string;\n credentialIdGeminiKey?: string;\n credentialIdDeepseekKey?: string;\n credentialIdGptBaseUrlKey?: string;\n}\n\nexport type AiProvider = 'openai' | 'anthropic' | 'gemini' | 'deepseek' | 'custom';\n\n/** Maps each provider to the adapter-config field holding its API key. */\nexport const PROVIDER_KEY_FIELD: Record<AiProvider, keyof AiConfigSlice> = {\n openai: 'gptKey',\n anthropic: 'claudeKey',\n gemini: 'geminiKey',\n deepseek: 'deepseekKey',\n custom: 'gptBaseUrlKey',\n};\n\n/**\n * Maps each provider to the adapter-config field holding the ID of its credential\n * in the central credential store (used in `manager` mode).\n */\nexport const PROVIDER_CREDENTIAL_ID_FIELD: Record<AiProvider, keyof AiConfigSlice> = {\n openai: 'credentialIdGptKey',\n anthropic: 'credentialIdClaudeKey',\n gemini: 'credentialIdGeminiKey',\n deepseek: 'credentialIdDeepseekKey',\n custom: 'credentialIdGptBaseUrlKey',\n};\n\n/**\n * Returns the configured credential ID (e.g. `system.credentials.anthropic`) for a provider\n * in `manager` mode, or an empty string if none/unknown provider.\n */\nexport function getProviderCredentialId(config: AiConfigSlice | undefined | null, provider: string): string {\n const cfg = config || {};\n const field = PROVIDER_CREDENTIAL_ID_FIELD[provider as AiProvider];\n return field ? (cfg[field] || '').toString().trim() : '';\n}\n\n/**\n * Resolve API key and base URL for a provider from adapter config.\n * Optional `messageBaseUrl` takes precedence over the stored `gptBaseUrl`\n * (used by the settings-dialog Test button where the user's form value\n * should win over the persisted value).\n */\nexport function resolveProviderCredentials(\n config: AiConfigSlice | undefined | null,\n provider: string,\n messageBaseUrl?: string,\n): { apiKey: string; baseUrl: string } {\n const cfg = config || {};\n const keyField = PROVIDER_KEY_FIELD[provider as AiProvider];\n const apiKey = keyField ? (cfg[keyField] || '').toString().trim() : '';\n /*\n * The stored `gptBaseUrl` belongs to the `custom` provider and to no other. `openai` used to\n * inherit it, which sent every request meant for api.openai.com - and the OpenAI key with it -\n * to whatever host the custom endpoint pointed at, with no way to opt out: an empty\n * `messageBaseUrl` counts as \"not provided\" and fell back to the stored value again (#2369).\n *\n * `openai` still honours an *explicit* `messageBaseUrl`, which is the escape hatch for a proxy\n * in front of OpenAI, but it no longer inherits the custom endpoint of another provider.\n */\n let baseUrl = '';\n if (provider === 'custom') {\n // An empty/whitespace messageBaseUrl counts as \"not provided\" and falls back to the stored\n // value, so the frontend can safely send `baseUrl: ''` without losing the configured URL.\n baseUrl = (messageBaseUrl || cfg.gptBaseUrl || '').toString().trim();\n } else if (provider === 'openai') {\n baseUrl = (messageBaseUrl || '').toString().trim();\n }\n return { apiKey, baseUrl };\n}\n\n/** Ceiling for an AI request, and the budget when the caller names none */\nexport const MAX_AI_REQUEST_TIMEOUT_MS = 600_000;\n\n/**\n * How long to wait for an AI endpoint, from the `timeout` the caller put in the message.\n *\n * The inline completion asks for a short budget because it must not sit on the editor, the chat\n * panel for a long one because a reasoning model takes its time. The field was sent all along but\n * never read, so both of them waited out the full ten minutes.\n *\n * @param messageTimeout the value from the sendTo message, in milliseconds\n */\nexport function resolveRequestTimeout(messageTimeout?: unknown): number {\n const requested = parseInt(messageTimeout as string, 10);\n // Nothing usable, or a zero - which is how Node itself spells \"no timeout\" - gets the ceiling\n if (isNaN(requested) || requested <= 0) {\n return MAX_AI_REQUEST_TIMEOUT_MS;\n }\n // A second is the floor: below that not even a local model gets a chance to answer\n return Math.min(Math.max(requested, 1000), MAX_AI_REQUEST_TIMEOUT_MS);\n}\n\n/**\n * For the testApiConnection sendTo command: if the caller supplied an apiKey\n * (settings-dialog form value), use it; otherwise fall back to the stored key.\n */\nexport function resolveTestCredentials(\n config: AiConfigSlice | undefined | null,\n provider: string,\n messageApiKey?: string,\n messageBaseUrl?: string,\n): { apiKey: string; baseUrl: string } {\n const fallback = resolveProviderCredentials(config, provider, messageBaseUrl);\n const explicitKey = (messageApiKey || '').toString().trim();\n return {\n apiKey: explicitKey || fallback.apiKey,\n baseUrl: fallback.baseUrl,\n };\n}\n\n/**\n * List of providers that have credentials configured in this.config.\n * Used by the `getAvailableAiProviders` sendTo command so the frontend\n * knows which provider icons/models to show without ever seeing a key.\n */\nexport function listAvailableProviders(\n config: AiConfigSlice | undefined | null,\n): { provider: AiProvider; baseUrl?: string }[] {\n const cfg = config || {};\n const providers: { provider: AiProvider; baseUrl?: string }[] = [];\n const manager = cfg.credentialType === 'manager';\n // A key-based provider is \"available\" if it has a stored key (manual mode)\n // or a selected credential ID (manager mode).\n const has = (provider: AiProvider, key: string | undefined | null): boolean =>\n manager ? !!getProviderCredentialId(cfg, provider) : !!(key || '').trim();\n if (has('openai', cfg.gptKey)) {\n providers.push({ provider: 'openai' });\n }\n if (has('anthropic', cfg.claudeKey)) {\n providers.push({ provider: 'anthropic' });\n }\n if (has('gemini', cfg.geminiKey)) {\n providers.push({ provider: 'gemini' });\n }\n if (has('deepseek', cfg.deepseekKey)) {\n providers.push({ provider: 'deepseek' });\n }\n // The custom/OpenAI-compatible endpoint is identified by its base URL (the key is optional,\n // e.g. local Ollama), so its availability does not depend on the credential mode.\n if ((cfg.gptBaseUrl || '').trim()) {\n providers.push({ provider: 'custom', baseUrl: cfg.gptBaseUrl });\n }\n return providers;\n}\n"]}
1
+ {"version":3,"file":"aiProviderResolver.js","sourceRoot":"","sources":["../../src/lib/aiProviderResolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Helpers for resolving AI provider credentials in sendTo handlers.\n *\n * Keys are stored as `encryptedNative` + `protectedNative` in io-package.json —\n * they are never sent from the frontend. The backend looks them up in `this.config`\n * based on the `provider` name sent along with each `chatCompletion` or\n * `testApiConnection` request.\n *\n * These functions are extracted so they can be unit-tested in isolation.\n */\n\n/** Configuration subset that carries AI credentials. */\nexport interface AiConfigSlice {\n gptKey?: string;\n gptBaseUrl?: string;\n gptBaseUrlKey?: string;\n claudeKey?: string;\n geminiKey?: string;\n deepseekKey?: string;\n /**\n * Where the API keys come from:\n * - `manual`: keys are stored directly in the adapter config (encryptedNative)\n * - `manager`: the config only stores the ID of a credential in the central\n * ioBroker credential store (`system.credentials.*`), resolved at runtime\n */\n credentialType?: 'manual' | 'manager';\n credentialIdGptKey?: string;\n credentialIdClaudeKey?: string;\n credentialIdGeminiKey?: string;\n credentialIdDeepseekKey?: string;\n credentialIdGptBaseUrlKey?: string;\n}\n\nexport type AiProvider = 'openai' | 'anthropic' | 'gemini' | 'deepseek' | 'custom';\n\n/** Maps each provider to the adapter-config field holding its API key. */\nexport const PROVIDER_KEY_FIELD: Record<AiProvider, keyof AiConfigSlice> = {\n openai: 'gptKey',\n anthropic: 'claudeKey',\n gemini: 'geminiKey',\n deepseek: 'deepseekKey',\n custom: 'gptBaseUrlKey',\n};\n\n/**\n * Maps each provider to the adapter-config field holding the ID of its credential\n * in the central credential store (used in `manager` mode).\n */\nexport const PROVIDER_CREDENTIAL_ID_FIELD: Record<AiProvider, keyof AiConfigSlice> = {\n openai: 'credentialIdGptKey',\n anthropic: 'credentialIdClaudeKey',\n gemini: 'credentialIdGeminiKey',\n deepseek: 'credentialIdDeepseekKey',\n custom: 'credentialIdGptBaseUrlKey',\n};\n\n/**\n * Returns the configured credential ID (e.g. `system.credentials.anthropic`) for a provider\n * in `manager` mode, or an empty string if none/unknown provider.\n */\nexport function getProviderCredentialId(config: AiConfigSlice | undefined | null, provider: string): string {\n const cfg = config || {};\n const field = PROVIDER_CREDENTIAL_ID_FIELD[provider as AiProvider];\n return field ? (cfg[field] || '').toString().trim() : '';\n}\n\n/**\n * Resolve API key and base URL for a provider from adapter config.\n *\n * Both come from the configuration and from nowhere else - above all not from the message that asked\n * for them. The key that is resolved here travels with the request as its authorisation, so a caller\n * who could name the address could have this instance carry the key to one of their own. An address\n * out of a message used to win over the stored one, which was the comfortable way to put a proxy in\n * front of OpenAI; a proxy belongs in the configuration now, entered once by whoever may configure\n * this instance. The test button of the settings dialog is the one exception - see\n * {@link resolveTestEndpoint}.\n *\n * The stored `gptBaseUrl` belongs to the `custom` provider and to no other. `openai` used to inherit\n * it, which sent every request meant for api.openai.com - and the OpenAI key with it - to whatever\n * host the custom endpoint pointed at (#2369).\n */\nexport function resolveProviderCredentials(\n config: AiConfigSlice | undefined | null,\n provider: string,\n): { apiKey: string; baseUrl: string } {\n const cfg = config || {};\n const keyField = PROVIDER_KEY_FIELD[provider as AiProvider];\n const apiKey = keyField ? (cfg[keyField] || '').toString().trim() : '';\n const baseUrl = provider === 'custom' ? (cfg.gptBaseUrl || '').toString().trim() : '';\n return { apiKey, baseUrl };\n}\n\n/**\n * The address the Test button of the settings dialog may try.\n *\n * The dialog tests what stands in the form rather than what was saved, because the first thing\n * anybody does is type a key and press it. The one thing it must not do is make this instance carry a\n * secret of its own to an address that came with the message, so an address out of the form counts\n * only together with a key out of the form: one's own key to one's own endpoint gives nothing away.\n * As soon as the key comes from this system - from the configuration or from the credential store -\n * the address comes from there too. And only the OpenAI-compatible provider has an address to try;\n * the form has no field for one anywhere else.\n *\n * @param config the adapter configuration\n * @param provider the provider that is being tested\n * @param form what the Test button sent\n * @param form.apiKey the key that stands in the form, if any\n * @param form.baseUrl the address that stands in the form, if any\n */\nexport function resolveTestEndpoint(\n config: AiConfigSlice | undefined | null,\n provider: string,\n form: { apiKey?: string; baseUrl?: string },\n): string {\n const stored = resolveProviderCredentials(config, provider).baseUrl;\n const formKey = (form.apiKey || '').toString().trim();\n const formUrl = (form.baseUrl || '').toString().trim();\n if (provider !== 'custom' || !formKey || !formUrl) {\n return stored;\n }\n return formUrl;\n}\n\n/** Ceiling for an AI request, and the budget when the caller names none */\nexport const MAX_AI_REQUEST_TIMEOUT_MS = 600_000;\n\n/**\n * How long to wait for an AI endpoint, from the `timeout` the caller put in the message.\n *\n * The inline completion asks for a short budget because it must not sit on the editor, the chat\n * panel for a long one because a reasoning model takes its time. The field was sent all along but\n * never read, so both of them waited out the full ten minutes.\n *\n * @param messageTimeout the value from the sendTo message, in milliseconds\n */\nexport function resolveRequestTimeout(messageTimeout?: unknown): number {\n const requested = parseInt(messageTimeout as string, 10);\n // Nothing usable, or a zero - which is how Node itself spells \"no timeout\" - gets the ceiling\n if (isNaN(requested) || requested <= 0) {\n return MAX_AI_REQUEST_TIMEOUT_MS;\n }\n // A second is the floor: below that not even a local model gets a chance to answer\n return Math.min(Math.max(requested, 1000), MAX_AI_REQUEST_TIMEOUT_MS);\n}\n\n/**\n * For the testApiConnection sendTo command: if the caller supplied an apiKey\n * (settings-dialog form value), use it; otherwise fall back to the stored key.\n */\nexport function resolveTestCredentials(\n config: AiConfigSlice | undefined | null,\n provider: string,\n messageApiKey?: string,\n messageBaseUrl?: string,\n): { apiKey: string; baseUrl: string } {\n const fallback = resolveProviderCredentials(config, provider);\n const explicitKey = (messageApiKey || '').toString().trim();\n return {\n apiKey: explicitKey || fallback.apiKey,\n // only together with a key of the form, and only for the endpoint of one's own\n baseUrl: resolveTestEndpoint(config, provider, { apiKey: explicitKey, baseUrl: messageBaseUrl }),\n };\n}\n\n/**\n * List of providers that have credentials configured in this.config.\n * Used by the `getAvailableAiProviders` sendTo command so the frontend\n * knows which provider icons/models to show without ever seeing a key.\n */\nexport function listAvailableProviders(\n config: AiConfigSlice | undefined | null,\n): { provider: AiProvider; baseUrl?: string }[] {\n const cfg = config || {};\n const providers: { provider: AiProvider; baseUrl?: string }[] = [];\n const manager = cfg.credentialType === 'manager';\n // A key-based provider is \"available\" if it has a stored key (manual mode)\n // or a selected credential ID (manager mode).\n const has = (provider: AiProvider, key: string | undefined | null): boolean =>\n manager ? !!getProviderCredentialId(cfg, provider) : !!(key || '').trim();\n if (has('openai', cfg.gptKey)) {\n providers.push({ provider: 'openai' });\n }\n if (has('anthropic', cfg.claudeKey)) {\n providers.push({ provider: 'anthropic' });\n }\n if (has('gemini', cfg.geminiKey)) {\n providers.push({ provider: 'gemini' });\n }\n if (has('deepseek', cfg.deepseekKey)) {\n providers.push({ provider: 'deepseek' });\n }\n // The custom/OpenAI-compatible endpoint is identified by its base URL (the key is optional,\n // e.g. local Ollama), so its availability does not depend on the credential mode.\n if ((cfg.gptBaseUrl || '').trim()) {\n providers.push({ provider: 'custom', baseUrl: cfg.gptBaseUrl });\n }\n return providers;\n}\n\n/** What a chat endpoint reported about how it finished a completion. */\nexport interface AiResponseInfo {\n /** Anthropic's `stop_reason` or the OpenAI-compatible `finish_reason`, when the endpoint sends one */\n finishReason?: string;\n /** Token counts, as far as the endpoint reports them */\n usage?: { input?: number; output?: number };\n}\n\n/** The handful of fields of a chat-completion response that say how it ended. */\nexport interface AiRawResponse {\n stop_reason?: unknown;\n choices?: { finish_reason?: unknown }[];\n usage?: {\n input_tokens?: unknown;\n output_tokens?: unknown;\n prompt_tokens?: unknown;\n completion_tokens?: unknown;\n };\n}\n\nfunction toCount(value: unknown): number | undefined {\n return typeof value === 'number' && isFinite(value) ? value : undefined;\n}\n\n/**\n * Pull the \"why did it stop\" fields out of a chat-completion response.\n *\n * Anthropic and the OpenAI-compatible endpoints spell both the reason and the token counts\n * differently. The adapter normalizes them and passes them on to the editor, so an answer that\n * was cut off or filtered can say so instead of arriving as an empty chat bubble.\n */\nexport function extractAiResponseInfo(parsed: AiRawResponse | null | undefined): AiResponseInfo {\n const info: AiResponseInfo = {};\n const reason = parsed?.stop_reason ?? parsed?.choices?.[0]?.finish_reason;\n if (typeof reason === 'string' && reason) {\n info.finishReason = reason;\n }\n const input = toCount(parsed?.usage?.input_tokens ?? parsed?.usage?.prompt_tokens);\n const output = toCount(parsed?.usage?.output_tokens ?? parsed?.usage?.completion_tokens);\n if (input !== undefined || output !== undefined) {\n info.usage = {\n ...(input !== undefined ? { input } : {}),\n ...(output !== undefined ? { output } : {}),\n };\n }\n return info;\n}\n\n/**\n * Why a 200 OK answer carried neither text nor a tool call.\n *\n * \"Empty response from API\" is true but useless - it sends the user looking for a broken key\n * when the usual cause is a model that spent its whole output budget on reasoning tokens. The\n * endpoint nearly always says why it stopped, so repeat that, and append a slice of the raw\n * body for the cases where it does not.\n *\n * @param info the normalized stop reason and token counts\n * @param rawBody the response body as it came off the wire\n */\nexport function describeEmptyAiResponse(info: AiResponseInfo, rawBody?: string): string {\n let why: string;\n switch (info.finishReason) {\n case 'max_tokens':\n case 'length':\n why = 'the model used up its output budget before writing an answer';\n break;\n case 'content_filter':\n case 'refusal':\n why = 'the endpoint filtered the answer away';\n break;\n case 'tool_use':\n case 'tool_calls':\n why = 'the model wanted to call a tool, but the answer carried no readable tool call';\n break;\n default:\n why = info.finishReason ? `the endpoint stopped with \"${info.finishReason}\"` : '';\n break;\n }\n const details: string[] = [];\n if (info.finishReason) {\n details.push(`stop reason: ${info.finishReason}`);\n }\n if (info.usage?.input !== undefined || info.usage?.output !== undefined) {\n details.push(`tokens in/out: ${info.usage?.input ?? '?'}/${info.usage?.output ?? '?'}`);\n }\n let message = 'The API answered without any content';\n if (why) {\n message += ` - ${why}`;\n }\n if (details.length) {\n message += ` (${details.join(', ')})`;\n }\n // Only worth showing when the endpoint told us nothing usable at all\n if (!info.finishReason && rawBody) {\n message += `. Response: ${rawBody.substring(0, 200)}`;\n }\n return message;\n}\n\n/** What Anthropic gets as `max_tokens` when the setting is empty or unusable */\nexport const DEFAULT_AI_MAX_TOKENS = 8192;\n/** Highest `max_tokens` the setting may ask for - beyond this every current model answers 400 */\nexport const MAX_AI_MAX_TOKENS = 200_000;\n\n/**\n * The output budget for an Anthropic request.\n *\n * Anthropic insists on `max_tokens`, so there is no \"let the endpoint decide\". Too small and a\n * generated script is cut off mid-line; too large and the model rejects the request outright, so\n * the configured value is clamped into a range every model can live with.\n *\n * @param configured the value from the adapter settings\n */\nexport function resolveMaxTokens(configured?: unknown): number {\n const requested = parseInt(configured as string, 10);\n if (isNaN(requested) || requested <= 0) {\n return DEFAULT_AI_MAX_TOKENS;\n }\n // 1024 is the floor: below that not even a short answer with its reasoning fits\n return Math.min(Math.max(requested, 1024), MAX_AI_MAX_TOKENS);\n}\n"]}
@@ -21,6 +21,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.translateToolsToAnthropic = translateToolsToAnthropic;
22
22
  exports.translateMessagesToAnthropic = translateMessagesToAnthropic;
23
23
  exports.translateAnthropicResponseToOpenAI = translateAnthropicResponseToOpenAI;
24
+ exports.describeAnthropicContent = describeAnthropicContent;
24
25
  /** Translate OpenAI function-tool definitions to Anthropic tool definitions. */
25
26
  function translateToolsToAnthropic(tools) {
26
27
  if (!Array.isArray(tools)) {
@@ -172,4 +173,40 @@ function translateAnthropicResponseToOpenAI(response) {
172
173
  }
173
174
  return result;
174
175
  }
176
+ /**
177
+ * Name the content blocks an answer consists of, for the log.
178
+ *
179
+ * When the translation above comes back empty although the endpoint reported a normal end and a
180
+ * few hundred output tokens, the whole question is *what* it sent instead - a `thinking` block, a
181
+ * block type that did not exist when this was written, an empty text. Without this the log can
182
+ * only say "no content", which is the one thing already known.
183
+ *
184
+ * @param response the parsed answer of the Anthropic API
185
+ */
186
+ function describeAnthropicContent(response) {
187
+ if (!response) {
188
+ return 'no response';
189
+ }
190
+ if (!Array.isArray(response.content)) {
191
+ return `content is ${typeof response.content}`;
192
+ }
193
+ if (!response.content.length) {
194
+ return 'no content blocks';
195
+ }
196
+ return response.content
197
+ .map(block => {
198
+ if (!block || typeof block !== 'object') {
199
+ return typeof block;
200
+ }
201
+ const type = block.type;
202
+ const name = typeof type === 'string' ? type : 'untyped';
203
+ // An empty text block is a different problem from a block nobody reads
204
+ if (name === 'text') {
205
+ const text = block.text;
206
+ return typeof text === 'string' ? `text(${text.length} chars)` : `text(${typeof text})`;
207
+ }
208
+ return name;
209
+ })
210
+ .join(', ');
211
+ }
175
212
  //# sourceMappingURL=anthropicAdapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"anthropicAdapter.js","sourceRoot":"","sources":["../../src/lib/anthropicAdapter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Translation layer between OpenAI-style chat-completion messages/tools and\n * Anthropic's native Messages API.\n *\n * The frontend (AiChatService / useAiChat) always speaks the OpenAI format:\n * - tools[] = [{ type: 'function', function: { name, description, parameters } }]\n * - assistant message with tool_calls[] = [{ id, type: 'function', function: { name, arguments } }]\n * - tool-result message with { role: 'tool', tool_call_id, content }\n * - response = { content, tool_calls? }\n *\n * Anthropic's API uses a different shape:\n * - tools[] = [{ name, description, input_schema }]\n * - assistant message content = [{ type: 'text', text }, { type: 'tool_use', id, name, input }]\n * - tool-result = user message with content = [{ type: 'tool_result', tool_use_id, content }]\n * - response body = { content: [text/tool_use blocks], stop_reason }\n *\n * These functions are pure so they can be unit-tested in isolation.\n */\n\nexport interface OpenAITool {\n type: 'function';\n function: {\n name: string;\n description?: string;\n parameters?: unknown;\n };\n}\n\nexport interface AnthropicTool {\n name: string;\n description?: string;\n input_schema: unknown;\n}\n\nexport interface OpenAIToolCall {\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n}\n\nexport interface OpenAIMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n content?: string | null;\n tool_calls?: OpenAIToolCall[];\n tool_call_id?: string;\n name?: string;\n}\n\ntype AnthropicContentBlock =\n | { type: 'text'; text: string }\n | { type: 'tool_use'; id: string; name: string; input: Record<string, unknown> }\n | { type: 'tool_result'; tool_use_id: string; content: string; is_error?: boolean };\n\nexport interface AnthropicMessage {\n role: 'user' | 'assistant';\n content: string | AnthropicContentBlock[];\n}\n\nexport interface AnthropicResponse {\n content?: AnthropicContentBlock[];\n stop_reason?: string;\n [key: string]: unknown;\n}\n\n/** Translate OpenAI function-tool definitions to Anthropic tool definitions. */\nexport function translateToolsToAnthropic(tools: unknown[] | undefined | null): AnthropicTool[] {\n if (!Array.isArray(tools)) {\n return [];\n }\n const result: AnthropicTool[] = [];\n for (const t of tools) {\n // Only `function`-type tools are supported. Anthropic uses a flat shape.\n const tool = t as OpenAITool;\n const fn = tool?.function;\n if (!fn?.name) {\n continue;\n }\n result.push({\n name: fn.name,\n description: fn.description,\n // OpenAI's `parameters` and Anthropic's `input_schema` share the JSON Schema shape.\n // If none is provided, Anthropic still requires an object schema.\n input_schema: fn.parameters || { type: 'object', properties: {} },\n });\n }\n return result;\n}\n\n/** Safe JSON.parse that returns an object on failure so we never throw mid-translation. */\nfunction safeParseArgs(args: string | undefined): Record<string, unknown> {\n if (!args) {\n return {};\n }\n try {\n const parsed: unknown = JSON.parse(args);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n return {};\n } catch {\n return {};\n }\n}\n\n/**\n * Translate a flat OpenAI-style message array into Anthropic's content-block format.\n * System messages are extracted and returned separately (Anthropic takes `system`\n * as a top-level request field, not an inline message).\n */\nexport function translateMessagesToAnthropic(messages: OpenAIMessage[] | undefined | null): {\n system: string;\n messages: AnthropicMessage[];\n} {\n if (!Array.isArray(messages)) {\n return { system: '', messages: [] };\n }\n\n const systemChunks: string[] = [];\n const out: AnthropicMessage[] = [];\n // Pending tool-results that must be grouped into a single `user` message per Anthropic's rules.\n let pendingToolResults: AnthropicContentBlock[] = [];\n\n const flushToolResults = (): void => {\n if (pendingToolResults.length) {\n out.push({ role: 'user', content: pendingToolResults });\n pendingToolResults = [];\n }\n };\n\n for (const m of messages) {\n if (!m || typeof m !== 'object') {\n continue;\n }\n\n if (m.role === 'system') {\n if (typeof m.content === 'string' && m.content) {\n systemChunks.push(m.content);\n }\n continue;\n }\n\n if (m.role === 'tool') {\n // Tool results accumulate; they're flushed when the next non-tool message appears.\n pendingToolResults.push({\n type: 'tool_result',\n tool_use_id: m.tool_call_id || '',\n content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content ?? ''),\n });\n continue;\n }\n\n flushToolResults();\n\n if (m.role === 'assistant') {\n const blocks: AnthropicContentBlock[] = [];\n if (typeof m.content === 'string' && m.content) {\n blocks.push({ type: 'text', text: m.content });\n }\n if (Array.isArray(m.tool_calls)) {\n for (const tc of m.tool_calls) {\n if (!tc?.id || !tc.function?.name) {\n continue;\n }\n blocks.push({\n type: 'tool_use',\n id: tc.id,\n name: tc.function.name,\n input: safeParseArgs(tc.function.arguments),\n });\n }\n }\n // Anthropic requires a non-empty content array for assistant messages.\n if (blocks.length) {\n out.push({ role: 'assistant', content: blocks });\n }\n continue;\n }\n\n if (m.role === 'user') {\n // Plain text user message. Content blocks aren't needed here.\n const text = typeof m.content === 'string' ? m.content : '';\n if (text) {\n out.push({ role: 'user', content: text });\n }\n continue;\n }\n }\n\n flushToolResults();\n\n return { system: systemChunks.join('\\n\\n'), messages: out };\n}\n\n/**\n * Translate an Anthropic Messages API response back into the OpenAI-style\n * `{ content, tool_calls }` shape that our frontend already understands.\n */\nexport function translateAnthropicResponseToOpenAI(response: AnthropicResponse | undefined | null): {\n content: string;\n tool_calls?: OpenAIToolCall[];\n} {\n if (!response || !Array.isArray(response.content)) {\n return { content: '' };\n }\n const textParts: string[] = [];\n const toolCalls: OpenAIToolCall[] = [];\n for (const block of response.content) {\n if (!block || typeof block !== 'object') {\n continue;\n }\n if (block.type === 'text' && typeof (block as { text?: unknown }).text === 'string') {\n textParts.push((block as { text: string }).text);\n } else if (block.type === 'tool_use') {\n const tu = block as { id?: string; name?: string; input?: unknown };\n toolCalls.push({\n id: tu.id || '',\n type: 'function',\n function: {\n name: tu.name || '',\n arguments: JSON.stringify(tu.input ?? {}),\n },\n });\n }\n }\n const result: { content: string; tool_calls?: OpenAIToolCall[] } = {\n content: textParts.join('\\n'),\n };\n if (toolCalls.length) {\n result.tool_calls = toolCalls;\n }\n return result;\n}\n"]}
1
+ {"version":3,"file":"anthropicAdapter.js","sourceRoot":"","sources":["../../src/lib/anthropicAdapter.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;AAmDH,8DAqBC;AAuBD,oEAkFC;AAMD,gFAkCC;AAYD,4DAyBC;AA5MD,gFAAgF;AAChF,SAAgB,yBAAyB,CAAC,KAAmC;IACzE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACpB,yEAAyE;QACzE,MAAM,IAAI,GAAG,CAAe,CAAC;QAC7B,MAAM,EAAE,GAAG,IAAI,EAAE,QAAQ,CAAC;QAC1B,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC;YACZ,SAAS;QACb,CAAC;QACD,MAAM,CAAC,IAAI,CAAC;YACR,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,WAAW,EAAE,EAAE,CAAC,WAAW;YAC3B,oFAAoF;YACpF,kEAAkE;YAClE,YAAY,EAAE,EAAE,CAAC,UAAU,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;SACpE,CAAC,CAAC;IACP,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,2FAA2F;AAC3F,SAAS,aAAa,CAAC,IAAwB;IAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO,EAAE,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACjE,OAAO,MAAiC,CAAC;QAC7C,CAAC;QACD,OAAO,EAAE,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,SAAgB,4BAA4B,CAAC,QAA4C;IAIrF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IACxC,CAAC;IAED,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,GAAG,GAAuB,EAAE,CAAC;IACnC,gGAAgG;IAChG,IAAI,kBAAkB,GAA4B,EAAE,CAAC;IAErD,MAAM,gBAAgB,GAAG,GAAS,EAAE;QAChC,IAAI,kBAAkB,CAAC,MAAM,EAAE,CAAC;YAC5B,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;YACxD,kBAAkB,GAAG,EAAE,CAAC;QAC5B,CAAC;IACL,CAAC,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC9B,SAAS;QACb,CAAC;QAED,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC7C,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACjC,CAAC;YACD,SAAS;QACb,CAAC;QAED,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,mFAAmF;YACnF,kBAAkB,CAAC,IAAI,CAAC;gBACpB,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE,CAAC,CAAC,YAAY,IAAI,EAAE;gBACjC,OAAO,EAAE,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;aACvF,CAAC,CAAC;YACH,SAAS;QACb,CAAC;QAED,gBAAgB,EAAE,CAAC;QAEnB,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACzB,MAAM,MAAM,GAA4B,EAAE,CAAC;YAC3C,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC7C,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC9B,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;oBAC5B,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;wBAChC,SAAS;oBACb,CAAC;oBACD,MAAM,CAAC,IAAI,CAAC;wBACR,IAAI,EAAE,UAAU;wBAChB,EAAE,EAAE,EAAE,CAAC,EAAE;wBACT,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI;wBACtB,KAAK,EAAE,aAAa,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;qBAC9C,CAAC,CAAC;gBACP,CAAC;YACL,CAAC;YACD,uEAAuE;YACvE,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAChB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YACrD,CAAC;YACD,SAAS;QACb,CAAC;QAED,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,8DAA8D;YAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,IAAI,IAAI,EAAE,CAAC;gBACP,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,CAAC;YACD,SAAS;QACb,CAAC;IACL,CAAC;IAED,gBAAgB,EAAE,CAAC;IAEnB,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,SAAgB,kCAAkC,CAAC,QAA8C;IAI7F,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAChD,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC3B,CAAC;IACD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAqB,EAAE,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACtC,SAAS;QACb,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,OAAQ,KAA4B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClF,SAAS,CAAC,IAAI,CAAE,KAA0B,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACnC,MAAM,EAAE,GAAG,KAAwD,CAAC;YACpE,SAAS,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE;gBACf,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE;oBACN,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE;oBACnB,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;iBAC5C;aACJ,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IACD,MAAM,MAAM,GAAuD;QAC/D,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;KAChC,CAAC;IACF,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;IAClC,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,wBAAwB,CAAC,QAA8C;IACnF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,OAAO,aAAa,CAAC;IACzB,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,OAAO,cAAc,OAAO,QAAQ,CAAC,OAAO,EAAE,CAAC;IACnD,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QAC3B,OAAO,mBAAmB,CAAC;IAC/B,CAAC;IACD,OAAO,QAAQ,CAAC,OAAO;SAClB,GAAG,CAAC,KAAK,CAAC,EAAE;QACT,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,OAAO,KAAK,CAAC;QACxB,CAAC;QACD,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;QAChD,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACzD,uEAAuE;QACvE,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YAClB,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;YAChD,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,QAAQ,OAAO,IAAI,GAAG,CAAC;QAC5F,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC","sourcesContent":["/**\n * Translation layer between OpenAI-style chat-completion messages/tools and\n * Anthropic's native Messages API.\n *\n * The frontend (AiChatService / useAiChat) always speaks the OpenAI format:\n * - tools[] = [{ type: 'function', function: { name, description, parameters } }]\n * - assistant message with tool_calls[] = [{ id, type: 'function', function: { name, arguments } }]\n * - tool-result message with { role: 'tool', tool_call_id, content }\n * - response = { content, tool_calls? }\n *\n * Anthropic's API uses a different shape:\n * - tools[] = [{ name, description, input_schema }]\n * - assistant message content = [{ type: 'text', text }, { type: 'tool_use', id, name, input }]\n * - tool-result = user message with content = [{ type: 'tool_result', tool_use_id, content }]\n * - response body = { content: [text/tool_use blocks], stop_reason }\n *\n * These functions are pure so they can be unit-tested in isolation.\n */\n\nexport interface OpenAITool {\n type: 'function';\n function: {\n name: string;\n description?: string;\n parameters?: unknown;\n };\n}\n\nexport interface AnthropicTool {\n name: string;\n description?: string;\n input_schema: unknown;\n}\n\nexport interface OpenAIToolCall {\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n}\n\nexport interface OpenAIMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n content?: string | null;\n tool_calls?: OpenAIToolCall[];\n tool_call_id?: string;\n name?: string;\n}\n\ntype AnthropicContentBlock =\n | { type: 'text'; text: string }\n | { type: 'tool_use'; id: string; name: string; input: Record<string, unknown> }\n | { type: 'tool_result'; tool_use_id: string; content: string; is_error?: boolean };\n\nexport interface AnthropicMessage {\n role: 'user' | 'assistant';\n content: string | AnthropicContentBlock[];\n}\n\nexport interface AnthropicResponse {\n content?: AnthropicContentBlock[];\n stop_reason?: string;\n [key: string]: unknown;\n}\n\n/** Translate OpenAI function-tool definitions to Anthropic tool definitions. */\nexport function translateToolsToAnthropic(tools: unknown[] | undefined | null): AnthropicTool[] {\n if (!Array.isArray(tools)) {\n return [];\n }\n const result: AnthropicTool[] = [];\n for (const t of tools) {\n // Only `function`-type tools are supported. Anthropic uses a flat shape.\n const tool = t as OpenAITool;\n const fn = tool?.function;\n if (!fn?.name) {\n continue;\n }\n result.push({\n name: fn.name,\n description: fn.description,\n // OpenAI's `parameters` and Anthropic's `input_schema` share the JSON Schema shape.\n // If none is provided, Anthropic still requires an object schema.\n input_schema: fn.parameters || { type: 'object', properties: {} },\n });\n }\n return result;\n}\n\n/** Safe JSON.parse that returns an object on failure so we never throw mid-translation. */\nfunction safeParseArgs(args: string | undefined): Record<string, unknown> {\n if (!args) {\n return {};\n }\n try {\n const parsed: unknown = JSON.parse(args);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n return {};\n } catch {\n return {};\n }\n}\n\n/**\n * Translate a flat OpenAI-style message array into Anthropic's content-block format.\n * System messages are extracted and returned separately (Anthropic takes `system`\n * as a top-level request field, not an inline message).\n */\nexport function translateMessagesToAnthropic(messages: OpenAIMessage[] | undefined | null): {\n system: string;\n messages: AnthropicMessage[];\n} {\n if (!Array.isArray(messages)) {\n return { system: '', messages: [] };\n }\n\n const systemChunks: string[] = [];\n const out: AnthropicMessage[] = [];\n // Pending tool-results that must be grouped into a single `user` message per Anthropic's rules.\n let pendingToolResults: AnthropicContentBlock[] = [];\n\n const flushToolResults = (): void => {\n if (pendingToolResults.length) {\n out.push({ role: 'user', content: pendingToolResults });\n pendingToolResults = [];\n }\n };\n\n for (const m of messages) {\n if (!m || typeof m !== 'object') {\n continue;\n }\n\n if (m.role === 'system') {\n if (typeof m.content === 'string' && m.content) {\n systemChunks.push(m.content);\n }\n continue;\n }\n\n if (m.role === 'tool') {\n // Tool results accumulate; they're flushed when the next non-tool message appears.\n pendingToolResults.push({\n type: 'tool_result',\n tool_use_id: m.tool_call_id || '',\n content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content ?? ''),\n });\n continue;\n }\n\n flushToolResults();\n\n if (m.role === 'assistant') {\n const blocks: AnthropicContentBlock[] = [];\n if (typeof m.content === 'string' && m.content) {\n blocks.push({ type: 'text', text: m.content });\n }\n if (Array.isArray(m.tool_calls)) {\n for (const tc of m.tool_calls) {\n if (!tc?.id || !tc.function?.name) {\n continue;\n }\n blocks.push({\n type: 'tool_use',\n id: tc.id,\n name: tc.function.name,\n input: safeParseArgs(tc.function.arguments),\n });\n }\n }\n // Anthropic requires a non-empty content array for assistant messages.\n if (blocks.length) {\n out.push({ role: 'assistant', content: blocks });\n }\n continue;\n }\n\n if (m.role === 'user') {\n // Plain text user message. Content blocks aren't needed here.\n const text = typeof m.content === 'string' ? m.content : '';\n if (text) {\n out.push({ role: 'user', content: text });\n }\n continue;\n }\n }\n\n flushToolResults();\n\n return { system: systemChunks.join('\\n\\n'), messages: out };\n}\n\n/**\n * Translate an Anthropic Messages API response back into the OpenAI-style\n * `{ content, tool_calls }` shape that our frontend already understands.\n */\nexport function translateAnthropicResponseToOpenAI(response: AnthropicResponse | undefined | null): {\n content: string;\n tool_calls?: OpenAIToolCall[];\n} {\n if (!response || !Array.isArray(response.content)) {\n return { content: '' };\n }\n const textParts: string[] = [];\n const toolCalls: OpenAIToolCall[] = [];\n for (const block of response.content) {\n if (!block || typeof block !== 'object') {\n continue;\n }\n if (block.type === 'text' && typeof (block as { text?: unknown }).text === 'string') {\n textParts.push((block as { text: string }).text);\n } else if (block.type === 'tool_use') {\n const tu = block as { id?: string; name?: string; input?: unknown };\n toolCalls.push({\n id: tu.id || '',\n type: 'function',\n function: {\n name: tu.name || '',\n arguments: JSON.stringify(tu.input ?? {}),\n },\n });\n }\n }\n const result: { content: string; tool_calls?: OpenAIToolCall[] } = {\n content: textParts.join('\\n'),\n };\n if (toolCalls.length) {\n result.tool_calls = toolCalls;\n }\n return result;\n}\n\n/**\n * Name the content blocks an answer consists of, for the log.\n *\n * When the translation above comes back empty although the endpoint reported a normal end and a\n * few hundred output tokens, the whole question is *what* it sent instead - a `thinking` block, a\n * block type that did not exist when this was written, an empty text. Without this the log can\n * only say \"no content\", which is the one thing already known.\n *\n * @param response the parsed answer of the Anthropic API\n */\nexport function describeAnthropicContent(response: AnthropicResponse | undefined | null): string {\n if (!response) {\n return 'no response';\n }\n if (!Array.isArray(response.content)) {\n return `content is ${typeof response.content}`;\n }\n if (!response.content.length) {\n return 'no content blocks';\n }\n return response.content\n .map(block => {\n if (!block || typeof block !== 'object') {\n return typeof block;\n }\n const type = (block as { type?: unknown }).type;\n const name = typeof type === 'string' ? type : 'untyped';\n // An empty text block is a different problem from a block nobody reads\n if (name === 'text') {\n const text = (block as { text?: unknown }).text;\n return typeof text === 'string' ? `text(${text.length} chars)` : `text(${typeof text})`;\n }\n return name;\n })\n .join(', ');\n}\n"]}