iobroker.ai-usage 0.2.0 → 0.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 (63) hide show
  1. package/README.md +135 -24
  2. package/admin/ai-usage.svg +12 -17
  3. package/admin/custom/assets/Components-Bq1fGAd7.js +1 -0
  4. package/admin/custom/assets/ConfigPanel-DGMF4_qT.js +1 -0
  5. package/admin/custom/assets/{_virtual_mf-localSharedImportMap___mfe_internal__AiUsageComponentSet__mf_owner__1-CXmnAfNY.js → _virtual_mf-localSharedImportMap___mfe_internal__AiUsageComponentSet__mf_owner__1-DKcsNxEw.js} +1 -1
  6. package/admin/custom/assets/{_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DwHNIjSR.js → _virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DzPBJWNQ.js} +1 -1
  7. package/admin/custom/assets/{_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-qu1s07FY.js → _virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-DEdJInQG.js} +3 -3
  8. package/admin/custom/assets/{_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-C8-GjKo4.js → _virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-CFn_lBXc.js} +1 -1
  9. package/admin/custom/assets/{_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__prebuild___mf_0_iobroker_mf_1_gui_mf_2_components__prebuild__-CQxWwR2r.js → _virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__prebuild___mf_0_iobroker_mf_1_gui_mf_2_components__prebuild__-DeLUTSLT.js} +1 -1
  10. package/admin/custom/assets/{hostInit-RHMRa462.js → hostInit-DoGxgbHj.js} +1 -1
  11. package/admin/custom/assets/index-CKngiVu3.js +1 -0
  12. package/admin/custom/assets/{lib-ByF76TCN.js → lib-MY71LxhX.js} +1 -1
  13. package/admin/custom/assets/{mf-entry-bootstrap-0-e070fa3e.js → mf-entry-bootstrap-0-eec08a33.js} +2 -2
  14. package/admin/custom/assets/virtualExposes-Dc9myzsk.js +1 -0
  15. package/admin/custom/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__AiUsageComponentSet__customComponents_js-l7jtElkM.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__AiUsageComponentSet__customComponents_js-CP4YA3u3.js} +1 -1
  16. package/admin/custom/assets/virtual_mf-exposes-ssr___mfe_internal__AiUsageComponentSet__customComponents_js-DlNU_Z38.js +2 -0
  17. package/admin/custom/assets/{virtual_mf-exposes___mfe_internal__AiUsageComponentSet__customComponents_js-BZ-CVpVo.js → virtual_mf-exposes___mfe_internal__AiUsageComponentSet__customComponents_js-CEfffc0D.js} +2 -2
  18. package/admin/custom/customComponents.js +1 -1
  19. package/admin/custom/i18n/de.json +24 -15
  20. package/admin/custom/i18n/en.json +25 -16
  21. package/admin/custom/i18n/es.json +25 -16
  22. package/admin/custom/i18n/fr.json +25 -16
  23. package/admin/custom/i18n/it.json +25 -16
  24. package/admin/custom/i18n/nl.json +25 -16
  25. package/admin/custom/i18n/pl.json +25 -16
  26. package/admin/custom/i18n/pt.json +25 -16
  27. package/admin/custom/i18n/ru.json +25 -16
  28. package/admin/custom/i18n/uk.json +25 -16
  29. package/admin/custom/i18n/zh-cn.json +25 -16
  30. package/admin/custom/mf-manifest.json +1 -1
  31. package/build/lib/http.js +33 -4
  32. package/build/lib/http.js.map +2 -2
  33. package/build/lib/jwt.js +59 -0
  34. package/build/lib/jwt.js.map +7 -0
  35. package/build/lib/poll-engine.js +86 -6
  36. package/build/lib/poll-engine.js.map +2 -2
  37. package/build/lib/provider.js.map +2 -2
  38. package/build/lib/providers/chatgpt-auth.js +125 -0
  39. package/build/lib/providers/chatgpt-auth.js.map +7 -0
  40. package/build/lib/providers/chatgpt-sub.js +122 -0
  41. package/build/lib/providers/chatgpt-sub.js.map +7 -0
  42. package/build/lib/providers/claude-auth.js.map +2 -2
  43. package/build/lib/providers/claude-sub.js +9 -5
  44. package/build/lib/providers/claude-sub.js.map +2 -2
  45. package/build/lib/providers/gemini-auth.js +135 -0
  46. package/build/lib/providers/gemini-auth.js.map +7 -0
  47. package/build/lib/providers/gemini-sub.js +147 -0
  48. package/build/lib/providers/gemini-sub.js.map +7 -0
  49. package/build/lib/pure-helpers.js +38 -6
  50. package/build/lib/pure-helpers.js.map +2 -2
  51. package/build/lib/sign-in.js +38 -0
  52. package/build/lib/sign-in.js.map +7 -0
  53. package/build/lib/snapshot-tree.js +21 -9
  54. package/build/lib/snapshot-tree.js.map +2 -2
  55. package/build/main.js +283 -151
  56. package/build/main.js.map +2 -2
  57. package/io-package.json +46 -12
  58. package/package.json +1 -1
  59. package/admin/custom/assets/Components-Bd545388.js +0 -1
  60. package/admin/custom/assets/ConfigPanel-qivVprTj.js +0 -1
  61. package/admin/custom/assets/index-B0J1NbOp.js +0 -1
  62. package/admin/custom/assets/virtualExposes-BZWQ_oUV.js +0 -1
  63. package/admin/custom/assets/virtual_mf-exposes-ssr___mfe_internal__AiUsageComponentSet__customComponents_js-CRK-nAdE.js +0 -2
package/README.md CHANGED
@@ -2,13 +2,14 @@
2
2
 
3
3
  **Release:** [![npm version](https://img.shields.io/npm/v/iobroker.ai-usage)](https://www.npmjs.com/package/iobroker.ai-usage) ![stable](https://iobroker.live/badges/ai-usage-stable.svg) ![Installations](https://iobroker.live/badges/ai-usage-installed.svg) [![npm downloads](https://img.shields.io/npm/dt/iobroker.ai-usage)](https://www.npmjs.com/package/iobroker.ai-usage)
4
4
 
5
- **Build:** [![Test and Release](https://github.com/krobipd/ioBroker.ai-usage/actions/workflows/test-and-release.yml/badge.svg)](https://github.com/krobipd/ioBroker.ai-usage/actions/workflows/test-and-release.yml) ![Node](https://img.shields.io/badge/node-%3E%3D22-brightgreen) ![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue) [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
5
+ **Build:** [![Test and Release](https://github.com/krobipd/ioBroker.ai-usage/actions/workflows/test-and-release.yml/badge.svg)](https://github.com/krobipd/ioBroker.ai-usage/actions/workflows/test-and-release.yml) ![Node](https://img.shields.io/badge/node-%3E%3D22-brightgreen) ![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue) [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE) [![Sentry](https://img.shields.io/badge/error%20reporting-Sentry-362d59?logo=sentry&logoColor=white)](https://github.com/ioBroker/plugin-sentry#plugin-sentry)
6
6
 
7
7
  **Support:** [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-ff5e5b?logo=ko-fi)](https://ko-fi.com/krobipd) [![PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://paypal.me/krobipd)
8
8
 
9
- Monitors your AI accounts in ioBroker: usage windows, limits, credits and costs of
10
- Claude, OpenAI, OpenRouter and DeepSeek as clean datapoints — for
11
- dashboards, history and automations ("send a message at 90 % of the weekly limit").
9
+ Monitors your AI accounts in ioBroker: usage windows, limits, credits and costs of your
10
+ Claude, ChatGPT and Google subscriptions plus OpenRouter, DeepSeek, OpenAI and Anthropic API
11
+ accounts — as clean datapoints for dashboards, history and automations ("send a message at
12
+ 90 % of the weekly limit").
12
13
 
13
14
  ---
14
15
 
@@ -17,12 +18,22 @@ dashboards, history and automations ("send a message at 90 % of the weekly limit
17
18
  - **Per-account monitoring** — one device node per AI account with harmonised datapoints: limit windows (percent + reset time), credits, costs and tokens
18
19
  - **Totals** — summed costs, the highest limit utilisation across all accounts, and one `limitReached` trigger for automations
19
20
  - **Warn threshold per account** — a single notification when an account crosses its threshold
21
+ - **Three subscriptions** — Claude, ChatGPT and Google are signed in with your own account; the settings page guides each sign-in step by step
20
22
  - **Central credentials** — API keys live in the admin's central credential storage and are shared with the admin AI assistant
21
23
  - **Read-only by design** — the adapter only reads usage data; it never calls, configures or writes to any AI service
24
+ - **Service status per account** — one indicator that tells apart "the AI service is down", "your sign-in is rejected" and "this host has no connection"
22
25
  - **Throttle-safe polling** — a hard minimum interval and automatic backoff protect your accounts from provider rate-limit lockouts
23
26
 
24
27
  ---
25
28
 
29
+ ## Sentry / Error reporting
30
+
31
+ **This adapter uses Sentry libraries to automatically report exceptions and code errors to the developers.** Reporting only happens if you have enabled error reporting in the ioBroker diagnostics (**System settings → Diagnostics and error reporting**). Only an anonymous installation ID is transmitted — no name, e-mail address or IP address.
32
+
33
+ For details and how to disable it, see the [Sentry plugin documentation](https://github.com/ioBroker/plugin-sentry#plugin-sentry). Error reporting requires js-controller 3.0 or newer.
34
+
35
+ ---
36
+
26
37
  ## Requirements
27
38
 
28
39
  - Node.js >= 22
@@ -33,16 +44,54 @@ dashboards, history and automations ("send a message at 90 % of the weekly limit
33
44
 
34
45
  ## Configuration
35
46
 
36
- The instance settings show your stored AI credentials (admin central storage, category AI) as
37
- simple on/off switches — switch on what you want to monitor. The Claude subscription has its own
38
- card with a guided sign-in: open the sign-in page, log in with your Claude account, paste the code,
39
- done. New API keys are added once under Settings → Credentials and are shared with the admin AI
40
- assistant.
47
+ The instance settings show one list of AI accounts. Switch on what you want to monitor:
48
+
49
+ | Account | How it is connected |
50
+ |---------|---------------------|
51
+ | **Claude subscription** | Sign in once with your Claude account (guided, in the settings) |
52
+ | **ChatGPT subscription** | Sign in once with your ChatGPT account (guided, in the settings) |
53
+ | **Google/Gemini subscription** | Sign in once with your Google account (guided, in the settings) |
54
+ | **OpenRouter, DeepSeek** | Pick the stored key from the admin's central credential storage |
55
+ | **OpenAI, Anthropic (organisation)** | Needs an **admin key** of your organisation — see below |
56
+
57
+ ### Signing in to a subscription
58
+
59
+ Each provider needs a different last step, and the settings page tells you which one:
60
+
61
+ - **Claude** — open the sign-in page, log in, copy the code shown there and paste it back.
62
+ - **ChatGPT** — the adapter shows a short code; type it on the OpenAI page it links to. The
63
+ settings page notices by itself once you confirmed. The adapter signs in separately from the
64
+ Codex CLI and does not disturb its session.
65
+ - **Google/Gemini** — open the sign-in page and log in. Google then sends the result to
66
+ `localhost`, so **your browser shows an error page ("site cannot be reached"). That is expected**
67
+ — the address bar still carries the sign-in result. Copy the **whole address** and paste it back.
68
+
69
+ > The three subscription endpoints are **not officially documented**. They are the same ones the
70
+ > providers' own tools use, but they can change without notice. If a subscription stops delivering
71
+ > data, that is the likely reason.
72
+ >
73
+ > **Verification status:** the Claude sign-in and read-out were tested against a live subscription.
74
+ > ChatGPT and Google/Gemini were built from the requests those providers' own tools make, but no
75
+ > live subscription of either was available to test them on — please open an issue if a value looks
76
+ > wrong or a sign-in step behaves differently than described.
77
+
78
+ ### API accounts with a key
79
+
80
+ Keys come from the admin's central credential storage (Settings → Credentials) and are shared with
81
+ the admin AI assistant. Two of them need a **different** key than the assistant uses:
82
+
83
+ - **OpenAI** — the usage and cost reports are organisation endpoints and need an **admin key**
84
+ created in the organisation settings.
85
+ - **Anthropic** — same, an **admin key** (`sk-ant-admin…`), which only an organisation
86
+ administrator can create. Personal accounts without an organisation cannot deliver these reports
87
+ at all; use the Claude subscription row instead.
88
+
89
+ Add such a key as its own entry in the credential storage (template "Key") and pick it in the row.
41
90
 
42
91
  | Option | Description | Default |
43
92
  |--------|-------------|---------|
44
- | **Warn at %** | Per account: one notification when a limit window crosses this utilisation | 80 |
45
- | **Poll interval** | How often each account is queried (seconds) | 300 |
93
+ | **Warn at %** | Per account: one notification when a plan-wide limit window crosses this utilisation | 80 |
94
+ | **Poll interval** | How often each account is queried, 60–3600 seconds. The floor is deliberate — asking too often gets the account throttled by the provider | 300 |
46
95
  | **Notifications** | One notification on threshold crossing or broken credentials | on |
47
96
 
48
97
  ---
@@ -51,29 +100,76 @@ assistant.
51
100
 
52
101
  ```
53
102
  ai-usage.0.
54
- ├── info.connection — at least one account reachable (bool)
103
+ ├── info.connection — at least one account is delivering data (bool)
55
104
  ├── total. — totals across all accounts
56
- │ ├── costs.* — summed real money (same currency only)
57
- │ ├── maxLimitPercent — highest window utilisation of any account
105
+ │ ├── costs.today/month/… — summed real money (same currency only)
106
+ │ ├── maxLimitPercent — highest plan-wide utilisation of any account
58
107
  │ ├── warningsActive — number of accounts above their threshold
59
- │ └── limitReached — any window full (automation trigger)
60
- └── <account>. — one device per configured account
61
- ├── info.* — provider, reachable, last update
62
- ├── limits.<window>.* — percent + reset time (session, week, per model, …)
63
- ├── credits.* — granted budget: used / limit / remaining / percent
64
- ├── costs.* — real money: today / month / projected
65
- └── tokens.* — token counters (API accounts)
108
+ │ ├── limitReached — a plan-wide window is full (automation trigger)
109
+ │ ├── accountsReachable — accounts currently delivering data
110
+ │ └── accounts — configured accounts
111
+ ├── claude / chatgpt / gemini — one node per subscription
112
+ │ ├── warning — this account is above its warn threshold (bool)
113
+ │ ├── limitReached — a plan-wide window of this account is full (bool)
114
+ │ ├── info.serviceOnline — the AI service itself answered (bool)
115
+ │ ├── info.state — ok · unauthorized · rate-limited · service-down · no-connection
116
+ │ ├── info.reachable — usage data was read successfully (bool)
117
+ │ ├── info.signedIn — the sign-in is in place (bool)
118
+ │ ├── info.provider — which provider this node speaks to
119
+ │ ├── info.lastUpdate — time of the last successful read
120
+ │ ├── limits.<window>.* — percent + reset time (session, week, per model, …)
121
+ │ └── credits.* — where the provider reports a balance
122
+ └── <name>-api — one node per key-based account
123
+ ├── warning / limitReached — same triggers as above
124
+ ├── info.* — same status states as above (no signedIn — it uses a key)
125
+ ├── credits.* / costs.* — granted budget and real money
126
+ └── tokens.* — token counters
66
127
  ```
67
128
 
68
129
  Only what an account's source actually delivers is created.
69
130
 
131
+ ### Is it online?
132
+
133
+ `info.serviceOnline` answers "is the AI service itself up", `info.state` says why not:
134
+
135
+ | State | What happened |
136
+ |-------|---------------|
137
+ | `ok` | Data was read |
138
+ | `unauthorized` | The service answered, but rejects the sign-in or key — the service is **up** |
139
+ | `rate-limited` | The service answered with a throttle; the adapter backs off and keeps the last values |
140
+ | `service-down` | The service answered with a fault of its own (reported immediately) |
141
+ | `no-connection` | The service was not reachable at all — reported after three attempts in a row, so a single hiccup does not flip the indicator |
142
+
143
+ ### Which limit raises the warning
144
+
145
+ Only **plan-wide** windows — your session and your week — decide `warning`, `limitReached` and
146
+ `total.maxLimitPercent`, and the warning always names the window it came from. A window that
147
+ belongs to a single model keeps its own datapoints but stays out of it: a model you never use can
148
+ sit at 100 % forever, and an alarm that never clears is worse than none. Google is the exception,
149
+ because there every bucket belongs to a model — those are your quota, so they do count.
150
+
151
+ Want a specific model watched anyway? Build the automation on its own datapoint,
152
+ `limits.<window>.percent`.
153
+
70
154
  ---
71
155
 
72
156
  ## Troubleshooting
73
157
 
74
- ### An account shows `reachable = false`
75
- Check the credential in the admin's central credential storage (Settings → Credentials)
76
- and the adapter log. Authentication errors raise one notification with the reason.
158
+ ### An account delivers no data
159
+ Read `info.state` first, it names the cause: `unauthorized` means the sign-in expired (sign in
160
+ again in the settings) or the key is not an admin key (see Configuration); `service-down` and
161
+ `no-connection` are outside your instance and clear up by themselves. The adapter log states the
162
+ same reason once and raises a single notification.
163
+
164
+ ### A subscription says "not signed in" although you just signed in
165
+ Save the settings first, then sign in — the row needs a saved account to attach the sign-in to.
166
+ After a successful sign-in the adapter queries the account immediately, so values appear within
167
+ seconds.
168
+
169
+ ### The object tree changed after updating to 0.3.0
170
+ Accounts now live under fixed ids (`claude`, `chatgpt`, `gemini`, `<name>-api`) and the separate
171
+ `auth` branch is gone — the sign-in state moved into `<account>.info.signedIn`. Old nodes are
172
+ removed automatically, and an existing Claude sign-in is carried over.
77
173
 
78
174
  ---
79
175
 
@@ -83,6 +179,21 @@ and the adapter log. Authentication errors raise one notification with the reaso
83
179
  Placeholder for the next version (at the beginning of the line):
84
180
  ### **WORK IN PROGRESS**
85
181
  -->
182
+ ### 0.4.0 (2026-08-26)
183
+
184
+ - Fixed: A limit that belongs to a single model no longer reports the whole account as full, and the warning names the window it came from instead of just "usage"
185
+ - New: Each account shows whether the AI service itself is online, telling a service outage apart from a rejected sign-in or a missing internet connection
186
+ - New: Error reporting via Sentry — crashes reach the developer automatically, but only if you enabled diagnostics and error reporting in the ioBroker system settings
187
+ - Changed: New adapter icon — a network of nodes instead of the dark tile, so it reads as AI at a glance and sits cleanly in both the light and the dark admin
188
+
189
+ ### 0.3.0 (2026-08-26)
190
+
191
+ - New: ChatGPT and Google/Gemini subscriptions can now be monitored like the Claude one — each with its own guided sign-in that the settings page walks you through step by step
192
+ - New: The ChatGPT and Gemini readouts use the same endpoints the providers' own tools use, but no live subscription was available to test them on — please report anything that looks wrong
193
+ - Changed: Each account now owns exactly one node in the object tree (`claude`, `chatgpt`, `gemini`, `<name>-api`); the separate sign-in branch is gone and old nodes are cleaned up automatically
194
+ - Fixed: After signing in, the account is queried immediately instead of waiting for the next poll — no restart needed
195
+ - Fixed: OpenAI and Anthropic rows now state that they need an organisation admin key, instead of failing with an unexplained rejection
196
+
86
197
  ### 0.2.0 (2026-08-26)
87
198
 
88
199
  - Changed: Completely new settings page — your stored AI credentials appear as simple on/off switches instead of a table, and new keys are picked up straight from the admin credential storage
@@ -1,19 +1,14 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
2
- <!-- Theme-fixed colors on an own background — never currentColor (renders black as <img>). -->
3
- <defs>
4
- <linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
5
- <stop offset="0" stop-color="#1c2733"/>
6
- <stop offset="1" stop-color="#2b3d52"/>
7
- </linearGradient>
8
- </defs>
9
- <rect x="4" y="4" width="120" height="120" rx="24" fill="url(#bg)"/>
10
- <!-- Gauge arc: track + filled usage portion -->
11
- <path d="M 28 88 A 40 40 0 1 1 100 88" fill="none" stroke="#3d5570" stroke-width="10" stroke-linecap="round"/>
12
- <path d="M 28 88 A 40 40 0 0 1 42 34" fill="none" stroke="#4fc3f7" stroke-width="10" stroke-linecap="round"/>
13
- <path d="M 42 34 A 40 40 0 0 1 92 40" fill="none" stroke="#ffb74d" stroke-width="10" stroke-linecap="round"/>
14
- <!-- Needle -->
15
- <line x1="64" y1="86" x2="88" y2="50" stroke="#eceff1" stroke-width="6" stroke-linecap="round"/>
16
- <circle cx="64" cy="86" r="7" fill="#eceff1"/>
17
- <!-- Spark: the AI -->
18
- <path d="M 64 100 l 4 8 l 8 4 l -8 4 l -4 8 l -4 -8 l -8 -4 l 8 -4 z" fill="#4fc3f7" transform="translate(0,-4) scale(0.9)" transform-origin="64 112"/>
2
+ <!-- Theme-fixed colors, transparent background — never currentColor (renders black as <img>). -->
3
+ <g stroke="#8fa0ad" stroke-width="7" stroke-linecap="round" opacity="0.75">
4
+ <line x1="28" y1="64" x2="64" y2="32"/>
5
+ <line x1="28" y1="64" x2="64" y2="96"/>
6
+ <line x1="64" y1="32" x2="100" y2="64"/>
7
+ <line x1="64" y1="96" x2="100" y2="64"/>
8
+ <line x1="64" y1="32" x2="64" y2="96"/>
9
+ </g>
10
+ <circle cx="28" cy="64" r="14" fill="#38bdf8"/>
11
+ <circle cx="64" cy="32" r="14" fill="#38bdf8"/>
12
+ <circle cx="64" cy="96" r="14" fill="#0ea5e9"/>
13
+ <circle cx="100" cy="64" r="14" fill="#f59e0b"/>
19
14
  </svg>
@@ -0,0 +1 @@
1
+ import{t as e}from"./ConfigPanel-DGMF4_qT.js";var t={ConfigPanel:e};export{t as default};
@@ -0,0 +1 @@
1
+ import{t as e}from"./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-DEdJInQG.js";import{Br as t,Dr as n,Er as r,Fi as i,Ha as a,Hi as o,Or as s,Ti as c,Tr as l,Va as u,Xr as d,_o as f,ai as p,ci as m,ei as h,ga as g,ii as _,in as v,kr as y,li as b,ni as x,oi as S}from"./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DzPBJWNQ.js";f();var C=[{provider:`claude-sub`,label:`Claude`,captionKey:`aiu_capClaude`},{provider:`chatgpt-sub`,label:`ChatGPT`,captionKey:`aiu_capChatgpt`},{provider:`gemini-sub`,label:`Gemini`,captionKey:`aiu_capGemini`}];function w(e,t){let n=`${e} ${t}`.toLowerCase();return n.includes(`gemini`)?null:n.includes(`anthropic`)||n.includes(`claude`)?{provider:`anthropic-api`,label:`Anthropic`,needsAdminKey:!0}:n.includes(`chatgpt`)||n.includes(`openai`)?{provider:`openai`,label:`OpenAI`,needsAdminKey:!0}:n.includes(`deepseek`)?{provider:`deepseek`,label:`DeepSeek`,needsAdminKey:!1}:n.includes(`openrouter`)||n.includes(`router`)?{provider:`openrouter`,label:`OpenRouter`,needsAdminKey:!1}:null}var T=[{provider:`openrouter`,label:`OpenRouter`,needsAdminKey:!1},{provider:`deepseek`,label:`DeepSeek`,needsAdminKey:!1},{provider:`openai`,label:`OpenAI`,needsAdminKey:!0},{provider:`anthropic-api`,label:`Anthropic`,needsAdminKey:!0}];function E(e,t){return e.find(e=>e.provider===t)}function D(e,t,n,r){let i=e.filter(e=>e.provider!==t);return n?[...i,{name:r,provider:t,credentialId:``,warnThreshold:80,enabled:!0}]:i}function O(e,t,n,r){let i=e.filter(e=>e.credentialId!==t.id);return!r||!n?i:[...i,{name:t.name,provider:n,credentialId:t.id,warnThreshold:80,enabled:!0}]}function k(e,t,n){let r=Math.min(100,Math.max(10,Math.round(Number(n))||80));return e.map(e=>(t.credentialId?e.credentialId===t.credentialId:e.provider===t.provider)?{...e,warnThreshold:r}:e)}var A=class extends e{constructor(e){super(e),g(this,`timer`,null),this.state={...this.state,credentials:[],credentialsLoaded:!1,signIn:{},drafts:{},providerChoice:{},busy:``}}async componentDidMount(){var e;(e=super.componentDidMount)==null||e.call(this),await this.loadCredentials(),await this.refreshSignIn(),this.timer=setInterval(()=>void this.refreshSignIn(),4e3)}componentWillUnmount(){var e;this.timer&&=(clearInterval(this.timer),null),(e=super.componentWillUnmount)==null||e.call(this)}async loadCredentials(){try{let e=await this.props.oContext.socket.getObjectViewSystem(`config`,`system.credentials.`,`system.credentials.香`),t=Object.values(e||{}).filter(e=>{var t;return!!e&&((t=e.native)==null?void 0:t.type)===`ai`}).map(e=>{var t,n;let r=e._id.substring(19),i=(t=e.common)==null?void 0:t.name,a=typeof i==`string`?i:(i==null?void 0:i.en)||Object.values(i||{})[0]||r;return{id:e._id,suffix:r,name:a,icon:typeof((n=e.common)==null?void 0:n.icon)==`string`?e.common.icon:void 0}}).sort((e,t)=>e.name.localeCompare(t.name));this.setState({credentials:t,credentialsLoaded:!0})}catch{this.setState({credentialsLoaded:!0})}}async refreshSignIn(){if(!this.props.alive)return;let e={};for(let t of C){if(!E(this.accounts(),t.provider))continue;let n=await this.ask(`signInStatus`,t.provider);n&&(e[t.provider]=n)}this.setState({signIn:e})}async ask(e,t,n){let r=this.props.oContext;try{let i=await r.socket.sendTo(`${r.adapterName}.${r.instance}`,e,{provider:t,value:n});return!i||i.error?{status:`failed`,reason:(i==null?void 0:i.error)||v.t(`aiu_noAnswer`)}:i}catch{return null}}async run(e,t,n){this.setState({busy:t});let r=await this.ask(e,t,n);this.setState(e=>({busy:``,signIn:r?{...e.signIn,[t]:r}:e.signIn,drafts:{...e.drafts,[t]:``}}))}accounts(){let t=e.getValue(this.props.data,`accounts`);return Array.isArray(t)?t:[]}commit(e){this.onChange(`accounts`,e)}renderThreshold(e,t,n){return u(d,{size:`small`,type:`number`,label:v.t(`aiu_warnAt`),defaultValue:t.warnThreshold||80,onBlur:e=>this.commit(k(this.accounts(),n,e.target.value)),slotProps:{htmlInput:{min:10,max:100,style:{width:60}},inputLabel:{shrink:!0}},sx:{ml:`auto`}},e)}renderSignIn(e){let t=this.state.signIn[e],i=this.state.busy===e;if(!this.props.alive)return u(c,{severity:`warning`,children:v.t(`aiu_instanceNotRunning`)});if(this.props.changed)return u(c,{severity:`info`,children:v.t(`aiu_saveFirst`)});if(!t)return u(b,{size:20});if(t.status===`signed-in`)return a(x,{sx:{display:`flex`,alignItems:`center`,gap:1,flexWrap:`wrap`},children:[u(y,{color:`success`}),u(h,{sx:{color:`success.main`},children:v.t(`aiu_signedIn`)}),u(_,{size:`small`,startIcon:u(r,{}),disabled:i,onClick:()=>void this.run(`signOut`,e),children:v.t(`aiu_signOut`)})]});if(t.status===`awaiting-device`)return a(x,{sx:{display:`flex`,flexDirection:`column`,gap:1.5},children:[u(h,{variant:`body2`,children:v.t(`aiu_deviceStep1`)}),a(x,{sx:{display:`flex`,gap:1,alignItems:`center`,flexWrap:`wrap`},children:[u(m,{label:t.userCode,sx:{fontSize:20,fontFamily:`monospace`,py:2.5,px:1}}),u(_,{size:`small`,startIcon:u(s,{}),onClick:()=>{var e;(e=navigator.clipboard)==null||e.writeText(t.userCode)},children:v.t(`aiu_copyCode`)}),u(_,{variant:`contained`,startIcon:u(n,{}),href:t.verificationUrl,target:`_blank`,rel:`noopener noreferrer`,children:v.t(`aiu_openPage`)})]}),u(c,{severity:`info`,children:v.t(`aiu_deviceWaiting`)})]});if(t.status===`awaiting-paste`){let r=t.flow===`paste-url`;return a(x,{sx:{display:`flex`,flexDirection:`column`,gap:1.5},children:[u(h,{variant:`body2`,children:v.t(r?`aiu_googleStep1`:`aiu_claudeStep1`)}),a(x,{sx:{display:`flex`,gap:1,flexWrap:`wrap`},children:[u(_,{variant:`contained`,startIcon:u(n,{}),href:t.url,target:`_blank`,rel:`noopener noreferrer`,children:v.t(`aiu_openSignIn`)}),u(_,{variant:`outlined`,startIcon:u(s,{}),onClick:()=>{var e;(e=navigator.clipboard)==null||e.writeText(t.url)},children:v.t(`aiu_copyLink`)})]}),r?u(c,{severity:`warning`,children:v.t(`aiu_googleErrorPageHint`)}):null,u(h,{variant:`body2`,children:v.t(r?`aiu_googleStep2`:`aiu_claudeStep2`)}),a(x,{sx:{display:`flex`,gap:1,alignItems:`center`,flexWrap:`wrap`},children:[u(d,{size:`small`,label:v.t(r?`aiu_addressLabel`:`aiu_codeLabel`),value:this.state.drafts[e]??``,onChange:t=>this.setState(n=>({drafts:{...n.drafts,[e]:t.target.value}})),sx:{minWidth:340,flexGrow:1}}),u(_,{variant:`contained`,disabled:i||!(this.state.drafts[e]??``).trim(),onClick:()=>void this.run(`signInSubmit`,e,this.state.drafts[e]),children:i?u(b,{size:20}):v.t(`aiu_redeem`)})]})]})}return a(x,{sx:{display:`flex`,flexDirection:`column`,gap:1},children:[t.status===`failed`?u(c,{severity:`error`,children:t.reason}):null,u(x,{children:u(_,{variant:`contained`,startIcon:u(n,{}),disabled:i,onClick:()=>void this.run(`signInStart`,e),children:i?u(b,{size:20}):v.t(`aiu_startSignIn`)})})]})}renderSubscriptionRow(e){let n=E(this.accounts(),e.provider);return a(x,{children:[a(x,{sx:{display:`flex`,alignItems:`center`,gap:1.5,py:1,borderBottom:1,borderColor:`divider`},children:[u(o,{sx:{width:28,height:28,bgcolor:`transparent`},children:u(l,{fontSize:`small`,color:`primary`})}),a(x,{sx:{minWidth:180},children:[u(h,{children:e.label}),u(h,{variant:`caption`,sx:{opacity:.7},children:v.t(e.captionKey)})]}),n?this.renderThreshold(`${e.provider}-t`,n,{provider:e.provider}):null,u(t,{checked:!!n,onChange:t=>this.commit(D(this.accounts(),e.provider,t.target.checked,e.label)),sx:{ml:n?0:`auto`}})]}),n?u(x,{sx:{pl:6,py:1.5,borderBottom:1,borderColor:`divider`},children:this.renderSignIn(e.provider)}):null]},e.provider)}renderCredentialRow(e){var n;let r=this.accounts(),s=r.find(t=>t.credentialId===e.id),f=w(e.suffix,e.name),p=(s==null?void 0:s.provider)||(f==null?void 0:f.provider)||this.state.providerChoice[e.id]||``,m=((n=T.find(e=>e.provider===p))==null?void 0:n.needsAdminKey)??(f==null?void 0:f.needsAdminKey)??!1,g=!f&&!this.state.providerChoice[e.id]&&!s;return a(x,{sx:{borderBottom:1,borderColor:`divider`},children:[a(x,{sx:{display:`flex`,alignItems:`center`,gap:1.5,py:1},children:[u(o,{src:e.icon,sx:{width:28,height:28,bgcolor:`transparent`},children:u(l,{fontSize:`small`})}),a(x,{sx:{minWidth:180},children:[u(h,{children:e.name}),u(h,{variant:`caption`,sx:{opacity:.7},children:v.t(`aiu_storedKey`)})]}),g?u(d,{select:!0,size:`small`,label:v.t(`aiu_provider`),value:this.state.providerChoice[e.id]||``,onChange:t=>this.setState(n=>({providerChoice:{...n.providerChoice,[e.id]:t.target.value}})),sx:{minWidth:170},children:T.map(e=>u(i,{value:e.provider,children:e.label},e.provider))}):null,s?this.renderThreshold(`${e.id}-t`,s,{credentialId:e.id}):null,u(t,{checked:!!s,disabled:!p,onChange:t=>this.commit(O(r,e,p,t.target.checked)),sx:{ml:s?0:`auto`}})]}),s&&m?u(c,{severity:`info`,sx:{mb:1},children:v.t(`aiu_adminKeyHint`)}):null]},e.id)}renderItem(){return u(x,{"data-testid":`aiu-config`,sx:{maxWidth:760},children:u(p,{variant:`outlined`,children:a(S,{children:[u(h,{variant:`h6`,sx:{mb:.5},children:v.t(`aiu_storedTitle`)}),u(h,{variant:`body2`,sx:{opacity:.8,mb:1},children:v.t(`aiu_storedHint`)}),C.map(e=>this.renderSubscriptionRow(e)),this.state.credentialsLoaded?this.state.credentials.map(e=>this.renderCredentialRow(e)):u(b,{size:24,sx:{mt:1}}),this.state.credentialsLoaded&&this.state.credentials.length===0?u(c,{severity:`info`,sx:{mt:1},children:v.t(`aiu_noCredentials`)}):null]})})})}};export{A as t};
@@ -1 +1 @@
1
- import{t as e}from"./vite-preload-helper-B7qeedMF.js";var t={react:async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DwHNIjSR.js`).then(e=>(e.yo(),e.vo)),[],import.meta.url),"react/jsx-runtime":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DwHNIjSR.js`).then(e=>e.Ua),[],import.meta.url),"react-dom":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DwHNIjSR.js`).then(e=>(e.Xa(),e.Ya)),[],import.meta.url),"react-dom/client":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-C8-GjKo4.js`).then(e=>e.n),[],import.meta.url),"@mui/material":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DwHNIjSR.js`).then(e=>e.Wi),[],import.meta.url),"@mui/icons-material":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DwHNIjSR.js`).then(e=>e.wr),[],import.meta.url),"@iobroker/gui-components":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__prebuild___mf_0_iobroker_mf_1_gui_mf_2_components__prebuild__-CQxWwR2r.js`),[],import.meta.url),"@iobroker/json-config":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-qu1s07FY.js`).then(e=>e.n),[],import.meta.url)},n={react:{name:`react`,version:`19.2.8`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n.react.loaded=!0;let{react:e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"react/jsx-runtime":{name:`react/jsx-runtime`,version:`19.2.8`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`react/jsx-runtime`].loaded=!0;let{"react/jsx-runtime":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"react-dom":{name:`react-dom`,version:`19.2.8`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`react-dom`].loaded=!0;let{"react-dom":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"react-dom/client":{name:`react-dom/client`,version:`19.2.8`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`react-dom/client`].loaded=!0;let{"react-dom/client":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"@mui/material":{name:`@mui/material`,version:`9.3.1`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`@mui/material`].loaded=!0;let{"@mui/material":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"@mui/icons-material":{name:`@mui/icons-material`,version:`9.3.1`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`@mui/icons-material`].loaded=!0;let{"@mui/icons-material":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"@iobroker/gui-components":{name:`@iobroker/gui-components`,version:`10.1.0`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!1,async get(){n[`@iobroker/gui-components`].loaded=!0;let{"@iobroker/gui-components":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"@iobroker/json-config":{name:`@iobroker/json-config`,version:`9.0.22`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`@iobroker/json-config`].loaded=!0;let{"@iobroker/json-config":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}}},r=[];export{r as usedRemotes,n as usedShared};
1
+ import{t as e}from"./vite-preload-helper-B7qeedMF.js";var t={react:async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DzPBJWNQ.js`).then(e=>(e.yo(),e.vo)),[],import.meta.url),"react/jsx-runtime":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DzPBJWNQ.js`).then(e=>e.Ua),[],import.meta.url),"react-dom":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DzPBJWNQ.js`).then(e=>(e.Xa(),e.Ya)),[],import.meta.url),"react-dom/client":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-CFn_lBXc.js`).then(e=>e.n),[],import.meta.url),"@mui/material":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DzPBJWNQ.js`).then(e=>e.Wi),[],import.meta.url),"@mui/icons-material":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-DzPBJWNQ.js`).then(e=>e.wr),[],import.meta.url),"@iobroker/gui-components":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__prebuild___mf_0_iobroker_mf_1_gui_mf_2_components__prebuild__-DeLUTSLT.js`),[],import.meta.url),"@iobroker/json-config":async()=>await e(()=>import(`./_virtual_mf___mfe_internal__AiUsageComponentSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-DEdJInQG.js`).then(e=>e.n),[],import.meta.url)},n={react:{name:`react`,version:`19.2.8`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n.react.loaded=!0;let{react:e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"react/jsx-runtime":{name:`react/jsx-runtime`,version:`19.2.8`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`react/jsx-runtime`].loaded=!0;let{"react/jsx-runtime":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"react-dom":{name:`react-dom`,version:`19.2.8`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`react-dom`].loaded=!0;let{"react-dom":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"react-dom/client":{name:`react-dom/client`,version:`19.2.8`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`react-dom/client`].loaded=!0;let{"react-dom/client":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"@mui/material":{name:`@mui/material`,version:`9.3.1`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`@mui/material`].loaded=!0;let{"@mui/material":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"@mui/icons-material":{name:`@mui/icons-material`,version:`9.3.1`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`@mui/icons-material`].loaded=!0;let{"@mui/icons-material":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"@iobroker/gui-components":{name:`@iobroker/gui-components`,version:`10.1.0`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!1,async get(){n[`@iobroker/gui-components`].loaded=!0;let{"@iobroker/gui-components":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}},"@iobroker/json-config":{name:`@iobroker/json-config`,version:`9.0.22`,scope:[`default`],loaded:!1,eager:!1,from:`AiUsageComponentSet`,canLiveRebind:!0,async get(){n[`@iobroker/json-config`].loaded=!0;let{"@iobroker/json-config":e}=t,r={...await e()};return r.__esModule!==!0&&Object.defineProperty(r,"__esModule",{value:!0,enumerable:!1}),function(){return r}},shareConfig:{singleton:!0,requiredVersion:`*`,strictVersion:!1,eager:!1}}},r=[];export{r as usedRemotes,n as usedShared};