iobroker.javascript 9.1.1 → 9.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +32 -16
  2. package/admin/assets/AiChatPanel-Cc1KscBJ.js +315 -0
  3. package/admin/assets/AiDatapointProvider-B0i3I5Fm.js +2 -0
  4. package/admin/assets/AiDiffView-RPozjjHf.js +1 -0
  5. package/admin/assets/AiInlineProvider-DkgjVSFQ.js +7 -0
  6. package/admin/assets/{Save-Cld9qv9i.js → Save-CkuNSiWL.js} +1 -1
  7. package/admin/assets/ScriptEditor-6qrtvwPL.js +2 -0
  8. package/admin/assets/ScriptEditorVanillaMonaco-bJua4sm1.js +3 -0
  9. package/admin/assets/applyCodeEdit-BdRnbz2g.js +1 -0
  10. package/admin/assets/{createSvgIcon-DPvF8xqu.js → createSvgIcon-DYs_tNrE.js} +1 -1
  11. package/admin/assets/docs-compact-CKNGiYh2.js +336 -0
  12. package/admin/assets/{index-BVPl8hv0.js → index-BZxCaQhO.js} +5 -5
  13. package/admin/assets/index-CYbVtccs.js +1267 -0
  14. package/admin/assets/index-CexrwGGC.js +986 -0
  15. package/admin/assets/{index-DFZipply.js → index-DsW7vBcg.js} +1 -1
  16. package/admin/assets/index-SHs7_wDh.js +1 -0
  17. package/admin/assets/{index-DlDUIfpA.js → index-dN73sbyQ.js} +1 -1
  18. package/admin/assets/index-wHNMOf-c.js +5 -0
  19. package/admin/assets/inheritsLoose-CIXm_zPk.js +29 -0
  20. package/admin/assets/inlineChatWidget-Cu6rb4Ar.js +2 -0
  21. package/admin/assets/inlineDiffController-DBLpPOe2.js +16 -0
  22. package/admin/assets/{iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-QWG5Arqe.js → iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-CV1_X-Lf.js} +1 -1
  23. package/admin/assets/{localSharedImportMap-xmSu9Qkg.js → localSharedImportMap-BCwqnmn4.js} +1 -1
  24. package/admin/assets/stateHoverProvider-CGChzV5W.js +3 -0
  25. package/admin/assets/useTheme-DuTJsNQ-.js +1 -0
  26. package/admin/assets/{virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-D-eF6r8M.js → virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-DNrEsMrg.js} +2 -2
  27. package/admin/custom/assets/{Components-B8x6wOMD.js → Components-B9ZyjeRI.js} +1 -1
  28. package/admin/custom/assets/{index-N2n19KrF.js → index-DNKzDki_.js} +152 -152
  29. package/admin/custom/assets/{index-DbXK0odl.js → index-NItS-TWp.js} +1 -1
  30. package/admin/custom/assets/index-sozs10Ij.js +960 -0
  31. package/admin/custom/assets/{localSharedImportMap-2Enh8EZe.js → localSharedImportMap-BxT0VwTO.js} +1 -1
  32. package/admin/custom/assets/{virtualExposes-CqrW7o8v.js → virtualExposes-jSvr-kK3.js} +1 -1
  33. package/admin/custom/assets/{virtual_mf-REMOTE_ENTRY_ID_ConfigCustomJavascriptSet__customComponents_js-BZZsMeVW.js → virtual_mf-REMOTE_ENTRY_ID_ConfigCustomJavascriptSet__customComponents_js-Br3IlnqO.js} +2 -2
  34. package/admin/custom/customComponents.js +1 -1
  35. package/admin/google-blockly/own/blocks_words.js +7 -0
  36. package/admin/google-blockly/own/field_oid.js +311 -37
  37. package/admin/i18n/de.json +8 -0
  38. package/admin/i18n/en.json +8 -0
  39. package/admin/i18n/es.json +8 -0
  40. package/admin/i18n/flat.txt +427 -0
  41. package/admin/i18n/fr.json +8 -0
  42. package/admin/i18n/it.json +8 -0
  43. package/admin/i18n/nl.json +8 -0
  44. package/admin/i18n/pl.json +8 -0
  45. package/admin/i18n/pt.json +8 -0
  46. package/admin/i18n/ru.json +8 -0
  47. package/admin/i18n/uk.json +8 -0
  48. package/admin/i18n/zh-cn.json +8 -0
  49. package/admin/img/anthropic.svg +1 -0
  50. package/admin/img/custom.svg +1 -0
  51. package/admin/img/deepseek.svg +1 -0
  52. package/admin/img/gemini.svg +1 -0
  53. package/admin/img/openai.svg +1 -0
  54. package/admin/jsonConfig.json +80 -18
  55. package/admin/mf-manifest.json +1 -1
  56. package/admin/remoteEntry.js +1 -1
  57. package/admin/tab.html +6 -6
  58. package/build/lib/aiProviderResolver.js +80 -0
  59. package/build/lib/aiProviderResolver.js.map +1 -0
  60. package/build/lib/anthropicAdapter.js +175 -0
  61. package/build/lib/anthropicAdapter.js.map +1 -0
  62. package/build/lib/debugger.js +2 -2
  63. package/build/lib/debugger.js.map +1 -1
  64. package/build/lib/inspect.js.map +1 -1
  65. package/build/lib/nodeModulesManagement.js +2 -2
  66. package/build/lib/nodeModulesManagement.js.map +1 -1
  67. package/build/lib/protectFs.js +5 -0
  68. package/build/lib/protectFs.js.map +1 -1
  69. package/build/lib/sandbox.js +9 -4
  70. package/build/lib/sandbox.js.map +1 -1
  71. package/build/main.js +190 -101
  72. package/build/main.js.map +1 -1
  73. package/build/types.d.ts +3 -0
  74. package/docs/de/README.md +81 -10
  75. package/docs/de/blockly.md +34 -0
  76. package/docs/en/README.md +81 -10
  77. package/docs/en/blockly.md +34 -0
  78. package/install/installTypings.js +1 -1
  79. package/io-package.json +82 -54
  80. package/package.json +7 -6
  81. package/admin/assets/OpenAiDialog-rhLuRLIM.js +0 -13
  82. package/admin/assets/ScriptEditor-C-fO5h68.js +0 -2
  83. package/admin/assets/ScriptEditorVanillaMonaco-DSYvOslZ.js +0 -1
  84. package/admin/assets/docs-BrInh2Pn.js +0 -2036
  85. package/admin/assets/index-C49cpVll.js +0 -5
  86. package/admin/assets/index-XSrHkgLE.js +0 -1230
  87. package/admin/assets/index-gIA8x-8f.js +0 -1
  88. package/admin/assets/index-q6iFaoFb.js +0 -986
  89. package/admin/assets/inheritsLoose-B0Ba5G9z.js +0 -29
  90. package/admin/assets/useTheme-hy6f3gra.js +0 -1
  91. package/admin/custom/assets/index-CYc31Gwg.js +0 -960
@@ -95,6 +95,13 @@
95
95
  "label": "Allow self-signed certificates for URL requests",
96
96
  "xs": 12,
97
97
  "sm": 12
98
+ },
99
+ "sortGlobalScriptsAlphabetically": {
100
+ "newLine": true,
101
+ "type": "checkbox",
102
+ "label": "Sort global scripts alphabetically",
103
+ "xs": 12,
104
+ "sm": 12
98
105
  }
99
106
  }
100
107
  },
@@ -126,7 +133,7 @@
126
133
  "_ai": {
127
134
  "type": "panel",
128
135
  "label": "AI settings",
129
- "icon": "data:image/svg+xml;base64,",
136
+ "icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0iY3VycmVudENvbG9yIiBkPSJNNy41IDUuNkwxMCA3IDguNiA0LjUgMTAgMiA3LjUgMy40IDUgMmwxLjQgMi41TDUgN3ptMTIgOS44TDE3IDE0bDEuNCAyLjVMMTcgMTlsMi41LTEuNEwyMiAxOWwtMS40LTIuNUwyMiAxNHpNMjIgMmwtMi41IDEuNEwxNyAybDEuNCAyLjVMMTcgN2wyLjUtMS40TDIyIDdsLTEuNC0yLjV6bS03LjYzIDUuMjlhLjk5Ni45OTYgMCAwMC0xLjQxIDBMMS4yOSAxOC45NmEuOTk2Ljk5NiAwIDAwMCAxLjQxbDIuMzQgMi4zNGMuMzkuMzkgMS4wMi4zOSAxLjQxIDBMMTYuNyAxMS4wNWEuOTk2Ljk5NiAwIDAwMC0xLjQxbC0yLjMzLTIuMzV6TTUuMDQgMTguOTZsLTEuNDEtMS40MSA4LjY5LTguNjkgMS40MSAxLjQxLTguNjkgOC42OXoiLz48L3N2Zz4=",
130
137
  "items": {
131
138
  "_aiDescription": {
132
139
  "type": "staticText",
@@ -139,61 +146,116 @@
139
146
  },
140
147
  "gptKey": {
141
148
  "newLine": true,
142
- "type": "text",
149
+ "type": "password",
143
150
  "label": "ChatGPT API key",
144
151
  "xs": 12,
145
- "sm": 12,
152
+ "sm": 9,
146
153
  "help": "platform.openai.com",
147
154
  "helpLink": "https://platform.openai.com/api-keys"
148
155
  },
156
+ "_testOpenAi": {
157
+ "type": "sendTo",
158
+ "label": "Test OpenAI",
159
+ "icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJjdXJyZW50Q29sb3IiPjxwYXRoIGQ9Ik0xMiAyQzYuNDggMiAyIDUuNTggMiAxMGMwIDIuMjQgMS4xMiA0LjI3IDIuOTMgNS43Mkw0IDIwbDQuMzUtMi4xOEM5LjUgMTguMjcgMTAuNzIgMTguNSAxMiAxOC41YzUuNTIgMCAxMC0zLjU4IDEwLThTMTcuNTIgMiAxMiAyem0tMSAxMUg4di0yaDNWOGgydjNoM3YyaC0zdjNoLTJ2LTN6Ii8+PC9zdmc+",
160
+ "command": "testApiConnection",
161
+ "jsonData": "{\"apiKey\": \"${data.gptKey}\", \"provider\": \"openai\"}",
162
+ "variant": "outlined",
163
+ "disabled": "!data.gptKey",
164
+ "xs": 12,
165
+ "sm": 3,
166
+ "showProcess": true
167
+ },
149
168
  "claudeKey": {
150
169
  "newLine": true,
151
- "type": "text",
170
+ "type": "password",
152
171
  "label": "Anthropic API key",
153
172
  "xs": 12,
154
- "sm": 12,
173
+ "sm": 9,
155
174
  "help": "console.anthropic.com",
156
175
  "helpLink": "https://console.anthropic.com/settings/keys"
157
176
  },
177
+ "_testClaude": {
178
+ "type": "sendTo",
179
+ "label": "Test Anthropic",
180
+ "icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJjdXJyZW50Q29sb3IiPjxwYXRoIGQ9Ik0xMiAyTDMgMjBoNGwxLjUtNGg3bDEuNSA0aDRMMTIgMnptMCA2bDIuNSA3aC01TDEyIDh6Ii8+PC9zdmc+",
181
+ "command": "testApiConnection",
182
+ "jsonData": "{\"apiKey\": \"${data.claudeKey}\", \"provider\": \"anthropic\"}",
183
+ "variant": "outlined",
184
+ "disabled": "!data.claudeKey",
185
+ "xs": 12,
186
+ "sm": 3,
187
+ "showProcess": true
188
+ },
158
189
  "geminiKey": {
159
190
  "newLine": true,
160
- "type": "text",
191
+ "type": "password",
161
192
  "label": "Gemini API key",
162
193
  "xs": 12,
163
- "sm": 12,
194
+ "sm": 9,
164
195
  "help": "aistudio.google.com",
165
196
  "helpLink": "https://aistudio.google.com/apikey"
166
197
  },
198
+ "_testGemini": {
199
+ "type": "sendTo",
200
+ "label": "Test Gemini",
201
+ "icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJjdXJyZW50Q29sb3IiPjxwYXRoIGQ9Ik0xMiAxbDMgN2g3bC01LjUgNC41TDE4LjUgMjAgMTIgMTUuNSA1LjUgMjBsMi03LjVMMiA4aDd6Ii8+PC9zdmc+",
202
+ "command": "testApiConnection",
203
+ "jsonData": "{\"apiKey\": \"${data.geminiKey}\", \"provider\": \"gemini\"}",
204
+ "variant": "outlined",
205
+ "disabled": "!data.geminiKey",
206
+ "xs": 12,
207
+ "sm": 3,
208
+ "showProcess": true
209
+ },
167
210
  "deepseekKey": {
168
211
  "newLine": true,
169
- "type": "text",
212
+ "type": "password",
170
213
  "label": "DeepSeek API key",
171
214
  "xs": 12,
172
- "sm": 12,
215
+ "sm": 9,
173
216
  "help": "platform.deepseek.com",
174
217
  "helpLink": "https://platform.deepseek.com/api_keys"
175
218
  },
219
+ "_testDeepseek": {
220
+ "type": "sendTo",
221
+ "label": "Test DeepSeek",
222
+ "icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJjdXJyZW50Q29sb3IiPjxwYXRoIGQ9Ik0xMCAyYTggOCAwIDAgMSA2LjMyIDEyLjkxbDQuMzkgNC4zOC0xLjQyIDEuNDItNC4zOC00LjM5QTggOCAwIDEgMSAxMCAyem0wIDJhNiA2IDAgMSAwIDAgMTIgNiA2IDAgMCAwIDAtMTJ6Ii8+PC9zdmc+",
223
+ "command": "testApiConnection",
224
+ "jsonData": "{\"apiKey\": \"${data.deepseekKey}\", \"provider\": \"deepseek\"}",
225
+ "variant": "outlined",
226
+ "disabled": "!data.deepseekKey",
227
+ "xs": 12,
228
+ "sm": 3,
229
+ "showProcess": true
230
+ },
176
231
  "gptBaseUrl": {
177
232
  "newLine": true,
178
233
  "type": "text",
179
234
  "label": "Custom API Base URL",
180
235
  "xs": 12,
181
- "sm": 12,
236
+ "sm": 5,
182
237
  "help": "Custom API Base URL help",
183
238
  "placeholder": "https://api.openai.com/v1"
184
239
  },
185
- "_testApiConnection": {
186
- "newLine": true,
240
+ "gptBaseUrlKey": {
241
+ "type": "text",
242
+ "label": "Custom API key",
243
+ "xs": 12,
244
+ "sm": 4,
245
+ "help": "Custom API key help",
246
+ "placeholder": "optional"
247
+ },
248
+ "_testCustom": {
187
249
  "type": "sendTo",
188
- "label": "Test API connection",
250
+ "label": "Test Custom API",
251
+ "icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJjdXJyZW50Q29sb3IiPjxwYXRoIGQ9Ik00IDFoMTZ2NUg0VjF6bTEgMXYzaDE0VjJINXptLTEgNmgxNnY1SDRWOHptMSAxdjNoMTRWOUg1em0tMSA2aDE2djVINHYtNXptMSAxdjNoMTR2LTNINXptMi0xMmgydjFIN1Yzem0wIDZoMnYxSDdWOXptMCA2aDJ2MUg3di0xeiIvPjwvc3ZnPg==",
189
252
  "command": "testApiConnection",
190
- "jsonData": "{\"apiKey\": \"${data.gptKey}\", \"baseUrl\": \"${data.gptBaseUrl}\"}",
253
+ "jsonData": "{\"apiKey\": \"${data.gptBaseUrlKey}\", \"baseUrl\": \"${data.gptBaseUrl}\", \"provider\": \"openai\"}",
191
254
  "variant": "outlined",
255
+ "disabled": "!data.gptBaseUrl",
192
256
  "xs": 12,
193
- "sm": 6,
194
- "alsoDependsOn": ["gptKey", "gptBaseUrl"],
195
- "showProcess": true,
196
- "resultStringToError": "error"
257
+ "sm": 3,
258
+ "showProcess": true
197
259
  }
198
260
  }
199
261
  }
@@ -1 +1 @@
1
- {"id":"iobroker_javascript","name":"iobroker_javascript","metaData":{"name":"iobroker_javascript","type":"app","buildInfo":{"buildVersion":"1.0.0","buildName":"iobroker_javascript"},"remoteEntry":{"name":"remoteEntry.js","path":"","type":"module"},"ssrRemoteEntry":{"name":"remoteEntry.js","path":"","type":"module"},"types":{"path":"","name":""},"globalName":"iobroker_javascript","pluginVersion":"0.2.5","publicPath":"./"},"shared":[{"id":"iobroker_javascript:react","name":"react","version":"18.3.1","requiredVersion":"*","assets":{"js":{"async":[],"sync":["assets/index-Dsh1HfIY.js"]},"css":{"async":[],"sync":[]}}},{"id":"iobroker_javascript:react-dom","name":"react-dom","version":"18.3.1","requiredVersion":"*","assets":{"js":{"async":[],"sync":["assets/index-BkyLyaYT.js"]},"css":{"async":[],"sync":[]}}},{"id":"iobroker_javascript:@mui/material","name":"@mui/material","version":"6.5.0","requiredVersion":"*","assets":{"js":{"async":[],"sync":["assets/index-DlDUIfpA.js"]},"css":{"async":[],"sync":[]}}},{"id":"iobroker_javascript:prop-types","name":"prop-types","version":"15.8.1","requiredVersion":"*","assets":{"js":{"async":[],"sync":["assets/index-CVZSzCXy.js"]},"css":{"async":[],"sync":[]}}},{"id":"iobroker_javascript:@iobroker/adapter-react-v5","name":"@iobroker/adapter-react-v5","version":"8.1.3","requiredVersion":"*","assets":{"js":{"async":[],"sync":["assets/index-q6iFaoFb.js"]},"css":{"async":[],"sync":[]}}}],"remotes":[],"exposes":[]}
1
+ {"id":"iobroker_javascript","name":"iobroker_javascript","metaData":{"name":"iobroker_javascript","type":"app","buildInfo":{"buildVersion":"1.0.0","buildName":"iobroker_javascript"},"remoteEntry":{"name":"remoteEntry.js","path":"","type":"module"},"ssrRemoteEntry":{"name":"remoteEntry.js","path":"","type":"module"},"types":{"path":"","name":""},"globalName":"iobroker_javascript","pluginVersion":"0.2.5","publicPath":"./"},"shared":[{"id":"iobroker_javascript:react","name":"react","version":"18.3.1","requiredVersion":"*","assets":{"js":{"async":[],"sync":["assets/index-Dsh1HfIY.js"]},"css":{"async":[],"sync":[]}}},{"id":"iobroker_javascript:react-dom","name":"react-dom","version":"18.3.1","requiredVersion":"*","assets":{"js":{"async":[],"sync":["assets/index-BkyLyaYT.js"]},"css":{"async":[],"sync":[]}}},{"id":"iobroker_javascript:@mui/material","name":"@mui/material","version":"6.5.0","requiredVersion":"*","assets":{"js":{"async":[],"sync":["assets/index-dN73sbyQ.js"]},"css":{"async":[],"sync":[]}}},{"id":"iobroker_javascript:prop-types","name":"prop-types","version":"15.8.1","requiredVersion":"*","assets":{"js":{"async":[],"sync":["assets/index-CVZSzCXy.js"]},"css":{"async":[],"sync":[]}}},{"id":"iobroker_javascript:@iobroker/adapter-react-v5","name":"@iobroker/adapter-react-v5","version":"8.1.8","requiredVersion":"*","assets":{"js":{"async":[],"sync":["assets/index-CexrwGGC.js"]},"css":{"async":[],"sync":[]}}}],"remotes":[],"exposes":[]}
@@ -1 +1 @@
1
- import"./assets/preload-helper-BDBacUwf.js";import{g as r,i as a}from"./assets/virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-D-eF6r8M.js";export{r as get,a as init};
1
+ import"./assets/preload-helper-BDBacUwf.js";import{g as r,i as a}from"./assets/virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-DNrEsMrg.js";export{r as get,a as init};
package/admin/tab.html CHANGED
@@ -115,19 +115,19 @@
115
115
  type="text/javascript"
116
116
  src="google-blockly/own/blocks_object.js"
117
117
  ></script>
118
- <script type="module" crossorigin src="./assets/index-XSrHkgLE.js"></script>
118
+ <script type="module" crossorigin src="./assets/index-CYbVtccs.js"></script>
119
119
  <link rel="modulepreload" crossorigin href="./assets/preload-helper-BDBacUwf.js">
120
- <link rel="modulepreload" crossorigin href="./assets/virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-D-eF6r8M.js">
120
+ <link rel="modulepreload" crossorigin href="./assets/virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-DNrEsMrg.js">
121
121
  <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare__react__loadShare__.mjs-CTZOFJS2.js">
122
122
  <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare__react__loadShare__.mjs_commonjs-proxy-CE9lvhW8.js">
123
123
  <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare__prop_mf_2_types__loadShare__.mjs-BCtSFofY.js">
124
- <link rel="modulepreload" crossorigin href="./assets/createSvgIcon-DPvF8xqu.js">
124
+ <link rel="modulepreload" crossorigin href="./assets/createSvgIcon-DYs_tNrE.js">
125
125
  <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare__react_mf_2_dom__loadShare__.mjs-DeVAS-oa.js">
126
126
  <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-RQRRZMX5.js">
127
- <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-QWG5Arqe.js">
127
+ <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare___mf_0_mui_mf_1_material__loadShare__.mjs-CV1_X-Lf.js">
128
128
  <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__.mjs-DkBjPSMw.js">
129
- <link rel="modulepreload" crossorigin href="./assets/index-C49cpVll.js">
130
- <link rel="modulepreload" crossorigin href="./assets/inheritsLoose-B0Ba5G9z.js">
129
+ <link rel="modulepreload" crossorigin href="./assets/index-wHNMOf-c.js">
130
+ <link rel="modulepreload" crossorigin href="./assets/inheritsLoose-CIXm_zPk.js">
131
131
  <link rel="stylesheet" crossorigin href="./assets/index-BTsjunTt.css">
132
132
  </head>
133
133
  <body>
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * Helpers for resolving AI provider credentials in sendTo handlers.
4
+ *
5
+ * Keys are stored as `encryptedNative` + `protectedNative` in io-package.json —
6
+ * they are never sent from the frontend. The backend looks them up in `this.config`
7
+ * based on the `provider` name sent along with each `chatCompletion` or
8
+ * `testApiConnection` request.
9
+ *
10
+ * These functions are extracted so they can be unit-tested in isolation.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.PROVIDER_KEY_FIELD = void 0;
14
+ exports.resolveProviderCredentials = resolveProviderCredentials;
15
+ exports.resolveTestCredentials = resolveTestCredentials;
16
+ exports.listAvailableProviders = listAvailableProviders;
17
+ /** Maps each provider to the adapter-config field holding its API key. */
18
+ exports.PROVIDER_KEY_FIELD = {
19
+ openai: 'gptKey',
20
+ anthropic: 'claudeKey',
21
+ gemini: 'geminiKey',
22
+ deepseek: 'deepseekKey',
23
+ custom: 'gptBaseUrlKey',
24
+ };
25
+ /**
26
+ * Resolve API key and base URL for a provider from adapter config.
27
+ * Optional `messageBaseUrl` takes precedence over the stored `gptBaseUrl`
28
+ * (used by the settings-dialog Test button where the user's form value
29
+ * should win over the persisted value).
30
+ */
31
+ function resolveProviderCredentials(config, provider, messageBaseUrl) {
32
+ const cfg = config || {};
33
+ const keyField = exports.PROVIDER_KEY_FIELD[provider];
34
+ const apiKey = keyField ? (cfg[keyField] || '').toString().trim() : '';
35
+ // baseUrl only applies to openai-compatible providers (custom / openai endpoint override).
36
+ // An empty/whitespace messageBaseUrl counts as "not provided" and falls back to the stored value,
37
+ // so the frontend can safely send `baseUrl: ''` without overriding a configured custom URL.
38
+ const baseUrl = provider === 'custom' || provider === 'openai'
39
+ ? (messageBaseUrl || cfg.gptBaseUrl || '').toString().trim()
40
+ : '';
41
+ return { apiKey, baseUrl };
42
+ }
43
+ /**
44
+ * For the testApiConnection sendTo command: if the caller supplied an apiKey
45
+ * (settings-dialog form value), use it; otherwise fall back to the stored key.
46
+ */
47
+ function resolveTestCredentials(config, provider, messageApiKey, messageBaseUrl) {
48
+ const fallback = resolveProviderCredentials(config, provider, messageBaseUrl);
49
+ const explicitKey = (messageApiKey || '').toString().trim();
50
+ return {
51
+ apiKey: explicitKey || fallback.apiKey,
52
+ baseUrl: fallback.baseUrl,
53
+ };
54
+ }
55
+ /**
56
+ * List of providers that have credentials configured in this.config.
57
+ * Used by the `getAvailableAiProviders` sendTo command so the frontend
58
+ * knows which provider icons/models to show without ever seeing a key.
59
+ */
60
+ function listAvailableProviders(config) {
61
+ const cfg = config || {};
62
+ const providers = [];
63
+ if ((cfg.gptKey || '').trim()) {
64
+ providers.push({ provider: 'openai' });
65
+ }
66
+ if ((cfg.claudeKey || '').trim()) {
67
+ providers.push({ provider: 'anthropic' });
68
+ }
69
+ if ((cfg.geminiKey || '').trim()) {
70
+ providers.push({ provider: 'gemini' });
71
+ }
72
+ if ((cfg.deepseekKey || '').trim()) {
73
+ providers.push({ provider: 'deepseek' });
74
+ }
75
+ if ((cfg.gptBaseUrl || '').trim()) {
76
+ providers.push({ provider: 'custom', baseUrl: cfg.gptBaseUrl });
77
+ }
78
+ return providers;
79
+ }
80
+ //# sourceMappingURL=aiProviderResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aiProviderResolver.js","sourceRoot":"","sources":["../../src/lib/aiProviderResolver.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AA6BH,gEAgBC;AAMD,wDAYC;AAOD,wDAqBC;AA7ED,0EAA0E;AAC7D,QAAA,kBAAkB,GAA4C;IACvE,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,WAAW;IACnB,QAAQ,EAAE,aAAa;IACvB,MAAM,EAAE,eAAe;CAC1B,CAAC;AAEF;;;;;GAKG;AACH,SAAgB,0BAA0B,CACtC,MAAwC,EACxC,QAAgB,EAChB,cAAuB;IAEvB,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC;IACzB,MAAM,QAAQ,GAAG,0BAAkB,CAAC,QAAsB,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,2FAA2F;IAC3F,kGAAkG;IAClG,4FAA4F;IAC5F,MAAM,OAAO,GACT,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ;QAC1C,CAAC,CAAC,CAAC,cAAc,IAAI,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE;QAC5D,CAAC,CAAC,EAAE,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,SAAgB,sBAAsB,CAClC,MAAwC,EACxC,QAAgB,EAChB,aAAsB,EACtB,cAAuB;IAEvB,MAAM,QAAQ,GAAG,0BAA0B,CAAC,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;IAC9E,MAAM,WAAW,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;IAC5D,OAAO;QACH,MAAM,EAAE,WAAW,IAAI,QAAQ,CAAC,MAAM;QACtC,OAAO,EAAE,QAAQ,CAAC,OAAO;KAC5B,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,SAAgB,sBAAsB,CAClC,MAAwC;IAExC,MAAM,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC;IACzB,MAAM,SAAS,GAAiD,EAAE,CAAC;IACnE,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5B,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/B,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/B,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACjC,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAChC,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC","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\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 * 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 // baseUrl only applies to openai-compatible providers (custom / openai endpoint override).\n // An empty/whitespace messageBaseUrl counts as \"not provided\" and falls back to the stored value,\n // so the frontend can safely send `baseUrl: ''` without overriding a configured custom URL.\n const baseUrl =\n provider === 'custom' || provider === 'openai'\n ? (messageBaseUrl || cfg.gptBaseUrl || '').toString().trim()\n : '';\n return { apiKey, baseUrl };\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 if ((cfg.gptKey || '').trim()) {\n providers.push({ provider: 'openai' });\n }\n if ((cfg.claudeKey || '').trim()) {\n providers.push({ provider: 'anthropic' });\n }\n if ((cfg.geminiKey || '').trim()) {\n providers.push({ provider: 'gemini' });\n }\n if ((cfg.deepseekKey || '').trim()) {\n providers.push({ provider: 'deepseek' });\n }\n if ((cfg.gptBaseUrl || '').trim()) {\n providers.push({ provider: 'custom', baseUrl: cfg.gptBaseUrl });\n }\n return providers;\n}\n"]}
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ /**
3
+ * Translation layer between OpenAI-style chat-completion messages/tools and
4
+ * Anthropic's native Messages API.
5
+ *
6
+ * The frontend (AiChatService / useAiChat) always speaks the OpenAI format:
7
+ * - tools[] = [{ type: 'function', function: { name, description, parameters } }]
8
+ * - assistant message with tool_calls[] = [{ id, type: 'function', function: { name, arguments } }]
9
+ * - tool-result message with { role: 'tool', tool_call_id, content }
10
+ * - response = { content, tool_calls? }
11
+ *
12
+ * Anthropic's API uses a different shape:
13
+ * - tools[] = [{ name, description, input_schema }]
14
+ * - assistant message content = [{ type: 'text', text }, { type: 'tool_use', id, name, input }]
15
+ * - tool-result = user message with content = [{ type: 'tool_result', tool_use_id, content }]
16
+ * - response body = { content: [text/tool_use blocks], stop_reason }
17
+ *
18
+ * These functions are pure so they can be unit-tested in isolation.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.translateToolsToAnthropic = translateToolsToAnthropic;
22
+ exports.translateMessagesToAnthropic = translateMessagesToAnthropic;
23
+ exports.translateAnthropicResponseToOpenAI = translateAnthropicResponseToOpenAI;
24
+ /** Translate OpenAI function-tool definitions to Anthropic tool definitions. */
25
+ function translateToolsToAnthropic(tools) {
26
+ if (!Array.isArray(tools)) {
27
+ return [];
28
+ }
29
+ const result = [];
30
+ for (const t of tools) {
31
+ // Only `function`-type tools are supported. Anthropic uses a flat shape.
32
+ const tool = t;
33
+ const fn = tool?.function;
34
+ if (!fn?.name) {
35
+ continue;
36
+ }
37
+ result.push({
38
+ name: fn.name,
39
+ description: fn.description,
40
+ // OpenAI's `parameters` and Anthropic's `input_schema` share the JSON Schema shape.
41
+ // If none is provided, Anthropic still requires an object schema.
42
+ input_schema: fn.parameters || { type: 'object', properties: {} },
43
+ });
44
+ }
45
+ return result;
46
+ }
47
+ /** Safe JSON.parse that returns an object on failure so we never throw mid-translation. */
48
+ function safeParseArgs(args) {
49
+ if (!args) {
50
+ return {};
51
+ }
52
+ try {
53
+ const parsed = JSON.parse(args);
54
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
55
+ return parsed;
56
+ }
57
+ return {};
58
+ }
59
+ catch {
60
+ return {};
61
+ }
62
+ }
63
+ /**
64
+ * Translate a flat OpenAI-style message array into Anthropic's content-block format.
65
+ * System messages are extracted and returned separately (Anthropic takes `system`
66
+ * as a top-level request field, not an inline message).
67
+ */
68
+ function translateMessagesToAnthropic(messages) {
69
+ if (!Array.isArray(messages)) {
70
+ return { system: '', messages: [] };
71
+ }
72
+ const systemChunks = [];
73
+ const out = [];
74
+ // Pending tool-results that must be grouped into a single `user` message per Anthropic's rules.
75
+ let pendingToolResults = [];
76
+ const flushToolResults = () => {
77
+ if (pendingToolResults.length) {
78
+ out.push({ role: 'user', content: pendingToolResults });
79
+ pendingToolResults = [];
80
+ }
81
+ };
82
+ for (const m of messages) {
83
+ if (!m || typeof m !== 'object') {
84
+ continue;
85
+ }
86
+ if (m.role === 'system') {
87
+ if (typeof m.content === 'string' && m.content) {
88
+ systemChunks.push(m.content);
89
+ }
90
+ continue;
91
+ }
92
+ if (m.role === 'tool') {
93
+ // Tool results accumulate; they're flushed when the next non-tool message appears.
94
+ pendingToolResults.push({
95
+ type: 'tool_result',
96
+ tool_use_id: m.tool_call_id || '',
97
+ content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content ?? ''),
98
+ });
99
+ continue;
100
+ }
101
+ flushToolResults();
102
+ if (m.role === 'assistant') {
103
+ const blocks = [];
104
+ if (typeof m.content === 'string' && m.content) {
105
+ blocks.push({ type: 'text', text: m.content });
106
+ }
107
+ if (Array.isArray(m.tool_calls)) {
108
+ for (const tc of m.tool_calls) {
109
+ if (!tc?.id || !tc.function?.name) {
110
+ continue;
111
+ }
112
+ blocks.push({
113
+ type: 'tool_use',
114
+ id: tc.id,
115
+ name: tc.function.name,
116
+ input: safeParseArgs(tc.function.arguments),
117
+ });
118
+ }
119
+ }
120
+ // Anthropic requires a non-empty content array for assistant messages.
121
+ if (blocks.length) {
122
+ out.push({ role: 'assistant', content: blocks });
123
+ }
124
+ continue;
125
+ }
126
+ if (m.role === 'user') {
127
+ // Plain text user message. Content blocks aren't needed here.
128
+ const text = typeof m.content === 'string' ? m.content : '';
129
+ if (text) {
130
+ out.push({ role: 'user', content: text });
131
+ }
132
+ continue;
133
+ }
134
+ }
135
+ flushToolResults();
136
+ return { system: systemChunks.join('\n\n'), messages: out };
137
+ }
138
+ /**
139
+ * Translate an Anthropic Messages API response back into the OpenAI-style
140
+ * `{ content, tool_calls }` shape that our frontend already understands.
141
+ */
142
+ function translateAnthropicResponseToOpenAI(response) {
143
+ if (!response || !Array.isArray(response.content)) {
144
+ return { content: '' };
145
+ }
146
+ const textParts = [];
147
+ const toolCalls = [];
148
+ for (const block of response.content) {
149
+ if (!block || typeof block !== 'object') {
150
+ continue;
151
+ }
152
+ if (block.type === 'text' && typeof block.text === 'string') {
153
+ textParts.push(block.text);
154
+ }
155
+ else if (block.type === 'tool_use') {
156
+ const tu = block;
157
+ toolCalls.push({
158
+ id: tu.id || '',
159
+ type: 'function',
160
+ function: {
161
+ name: tu.name || '',
162
+ arguments: JSON.stringify(tu.input ?? {}),
163
+ },
164
+ });
165
+ }
166
+ }
167
+ const result = {
168
+ content: textParts.join('\n'),
169
+ };
170
+ if (toolCalls.length) {
171
+ result.tool_calls = toolCalls;
172
+ }
173
+ return result;
174
+ }
175
+ //# sourceMappingURL=anthropicAdapter.js.map
@@ -0,0 +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"]}
@@ -23,7 +23,7 @@ exports.default = createRepl;
23
23
  * IN THE SOFTWARE.
24
24
  */
25
25
  const node_path_1 = require("node:path");
26
- const repl_1 = require("repl");
26
+ const node_repl_1 = require("node:repl");
27
27
  const node_util_1 = require("node:util");
28
28
  const node_vm_1 = require("node:vm");
29
29
  const node_url_1 = require("node:url");
@@ -1118,7 +1118,7 @@ function createRepl(inspector) {
1118
1118
  useGlobal: false,
1119
1119
  ignoreUndefined: true,
1120
1120
  };
1121
- repl = (0, repl_1.start)(replOptions);
1121
+ repl = (0, node_repl_1.start)(replOptions);
1122
1122
  initializeContext(repl.context);
1123
1123
  repl.on('reset', initializeContext);
1124
1124
  repl.defineCommand('interrupt', () => {