openmagic 0.8.2 → 0.9.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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var OpenMagicToolbar=(()=>{var A=`
2
+ "use strict";var OpenMagicToolbar=(()=>{var D=`
3
3
  :host {
4
4
  all: initial;
5
5
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
@@ -9,27 +9,34 @@
9
9
  }
10
10
 
11
11
  * { box-sizing: border-box; margin: 0; padding: 0; }
12
-
13
12
  .om-hidden { display: none !important; }
14
13
 
15
- /* \u2500\u2500 Pill Bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
16
- .om-pill {
14
+ /* \u2500\u2500 Unified Toolbar Container \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
15
+ .om-toolbar {
17
16
  position: fixed;
18
- bottom: 24px;
19
- right: 24px;
17
+ bottom: 20px;
18
+ right: 20px;
20
19
  z-index: 2147483647;
20
+ width: 420px;
21
+ display: flex;
22
+ flex-direction: column;
23
+ background: #111125;
24
+ border: 1px solid rgba(108, 92, 231, 0.18);
25
+ border-radius: 14px;
26
+ box-shadow: 0 6px 32px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.02);
27
+ overflow: hidden;
28
+ }
29
+
30
+ /* \u2500\u2500 Header Bar (brand + tools) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
31
+ .om-toolbar-header {
21
32
  display: flex;
22
33
  align-items: center;
23
34
  gap: 2px;
24
- padding: 5px 10px 5px 4px;
25
- background: linear-gradient(135deg, #111125 0%, #191938 100%);
26
- border: 1px solid rgba(108, 92, 231, 0.2);
27
- border-radius: 12px;
28
- user-select: none;
29
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.03);
30
- transition: box-shadow 0.2s;
35
+ padding: 6px 10px 6px 5px;
36
+ border-bottom: 1px solid rgba(255,255,255,0.04);
37
+ background: rgba(108, 92, 231, 0.03);
38
+ flex-shrink: 0;
31
39
  }
32
- .om-pill:hover { box-shadow: 0 6px 28px rgba(108, 92, 231, 0.2), inset 0 1px 0 rgba(255,255,255,0.03); }
33
40
 
34
41
  .om-grab {
35
42
  display: flex; align-items: center; justify-content: center;
@@ -46,7 +53,7 @@
46
53
  .om-pill-icon { color: #a29bfe; flex-shrink: 0; }
47
54
  .om-pill-text { font-size: 11px; font-weight: 700; color: #a29bfe; letter-spacing: 0.3px; white-space: nowrap; }
48
55
 
49
- .om-pill-divider { width: 1px; height: 18px; background: rgba(255,255,255,0.07); margin: 0 3px; }
56
+ .om-pill-divider { width: 1px; height: 18px; background: rgba(255,255,255,0.06); margin: 0 3px; flex-shrink: 0; }
50
57
 
51
58
  .om-pill-btn {
52
59
  background: none; border: none; color: #555; cursor: pointer;
@@ -58,7 +65,7 @@
58
65
  .om-pill-btn.active { background: rgba(108, 92, 231, 0.25); color: #c4b5fd; }
59
66
 
60
67
  .om-status-dot {
61
- width: 7px; height: 7px; border-radius: 50%; margin-left: 4px; flex-shrink: 0;
68
+ width: 7px; height: 7px; border-radius: 50%; margin-left: auto; flex-shrink: 0;
62
69
  }
63
70
  .om-status-dot.connected { background: #00b894; }
64
71
  .om-status-dot.disconnected { background: #e94560; }
@@ -73,120 +80,87 @@
73
80
  50% { box-shadow: 0 0 0 5px rgba(253,203,110,0); }
74
81
  }
75
82
 
76
- /* \u2500\u2500 Prompt Bar (always visible) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
77
- .om-prompt-bar {
78
- position: fixed;
79
- bottom: 62px;
80
- right: 24px;
81
- z-index: 2147483647;
82
- display: flex;
83
- align-items: center;
84
- width: 420px;
85
- background: #151528;
86
- border: 1px solid rgba(108, 92, 231, 0.15);
87
- border-radius: 12px;
88
- padding: 4px;
89
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
90
- transition: border-color 0.2s, box-shadow 0.2s;
83
+ /* \u2500\u2500 Panel (expandable area between header and prompt) \u2500\u2500 */
84
+ .om-panel {
85
+ max-height: 420px;
86
+ overflow: hidden;
87
+ border-bottom: 1px solid rgba(255,255,255,0.04);
88
+ animation: om-expand 0.15s ease;
91
89
  }
92
- .om-prompt-bar:focus-within {
93
- border-color: rgba(108, 92, 231, 0.4);
94
- box-shadow: 0 4px 24px rgba(108, 92, 231, 0.15);
90
+ @keyframes om-expand {
91
+ from { max-height: 0; opacity: 0; }
92
+ to { max-height: 420px; opacity: 1; }
95
93
  }
96
94
 
97
- .om-prompt-input {
98
- flex: 1;
99
- background: transparent;
100
- border: none;
101
- color: #e0e0e0;
102
- font-size: 13px;
103
- font-family: inherit;
104
- padding: 8px 12px;
105
- outline: none;
106
- min-width: 0;
95
+ .om-panel-body {
96
+ overflow-y: auto; padding: 12px;
97
+ max-height: 420px;
98
+ }
99
+ .om-panel-body::-webkit-scrollbar { width: 5px; }
100
+ .om-panel-body::-webkit-scrollbar-track { background: transparent; }
101
+ .om-panel-body::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; }
102
+
103
+ /* \u2500\u2500 Prompt Row (always visible at bottom) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
104
+ .om-prompt-row {
105
+ display: flex;
106
+ align-items: center;
107
+ padding: 6px;
108
+ gap: 4px;
109
+ flex-shrink: 0;
107
110
  }
108
- .om-prompt-input::placeholder { color: #444; }
109
111
 
110
112
  .om-prompt-context {
111
- display: flex; gap: 3px; padding: 0 4px; flex-shrink: 0;
113
+ display: flex; gap: 3px; flex-shrink: 0;
112
114
  }
113
115
  .om-prompt-chip {
114
116
  display: flex; align-items: center; gap: 3px;
115
- padding: 3px 7px; background: rgba(108, 92, 231, 0.1);
116
- border: 1px solid rgba(108, 92, 231, 0.15);
117
+ padding: 3px 7px; background: rgba(108, 92, 231, 0.08);
118
+ border: 1px solid rgba(108, 92, 231, 0.12);
117
119
  border-radius: 6px; font-size: 10px; color: #a29bfe;
118
120
  cursor: default; white-space: nowrap;
119
121
  }
120
122
  .om-prompt-chip-x {
121
123
  background: none; border: none; color: #a29bfe; cursor: pointer;
122
- font-size: 12px; line-height: 1; padding: 0 1px; opacity: 0.6;
124
+ font-size: 11px; line-height: 1; padding: 0 1px; opacity: 0.5;
123
125
  }
124
126
  .om-prompt-chip-x:hover { opacity: 1; }
125
127
 
128
+ .om-prompt-input {
129
+ flex: 1;
130
+ background: rgba(255,255,255,0.04);
131
+ border: 1px solid rgba(255,255,255,0.06);
132
+ border-radius: 8px;
133
+ color: #e0e0e0;
134
+ font-size: 13px;
135
+ font-family: inherit;
136
+ padding: 7px 10px;
137
+ outline: none;
138
+ min-width: 0;
139
+ transition: border-color 0.15s;
140
+ }
141
+ .om-prompt-input:focus { border-color: rgba(108, 92, 231, 0.4); }
142
+ .om-prompt-input::placeholder { color: #3a3a5a; }
143
+
126
144
  .om-prompt-send {
127
145
  display: flex; align-items: center; justify-content: center;
128
- width: 32px; height: 32px; flex-shrink: 0;
146
+ width: 30px; height: 30px; flex-shrink: 0;
129
147
  background: #6c5ce7; border: none; border-radius: 8px;
130
148
  color: white; cursor: pointer; transition: background 0.15s;
131
149
  }
132
150
  .om-prompt-send:hover { background: #7c6cf7; }
133
- .om-prompt-send:disabled { background: #2a2a4a; color: #555; cursor: not-allowed; }
134
-
135
- /* \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
136
- .om-panel {
137
- position: fixed;
138
- bottom: 110px;
139
- right: 24px;
140
- z-index: 2147483647;
141
- width: 420px;
142
- max-height: 520px;
143
- background: #151528;
144
- border: 1px solid rgba(108, 92, 231, 0.15);
145
- border-radius: 14px;
146
- box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
147
- display: flex;
148
- flex-direction: column;
149
- overflow: hidden;
150
- animation: om-slide-up 0.15s ease;
151
- }
152
- @keyframes om-slide-up {
153
- from { opacity: 0; transform: translateY(6px); }
154
- to { opacity: 1; transform: translateY(0); }
155
- }
156
-
157
- .om-panel-header {
158
- display: flex; align-items: center; gap: 8px;
159
- padding: 10px 14px;
160
- border-bottom: 1px solid rgba(255,255,255,0.04);
161
- background: rgba(108, 92, 231, 0.03);
162
- }
163
- .om-panel-title { font-size: 12px; font-weight: 600; color: #a29bfe; }
164
- .om-panel-version { font-size: 10px; color: #444; margin-left: auto; }
165
- .om-panel-close {
166
- background: none; border: none; color: #555; cursor: pointer;
167
- padding: 2px 5px; border-radius: 4px; line-height: 1;
168
- display: flex; align-items: center; justify-content: center;
169
- }
170
- .om-panel-close:hover { color: #ccc; background: rgba(255,255,255,0.05); }
171
-
172
- .om-panel-body {
173
- flex: 1; overflow-y: auto; padding: 14px;
174
- }
175
- .om-panel-body::-webkit-scrollbar { width: 5px; }
176
- .om-panel-body::-webkit-scrollbar-track { background: transparent; }
177
- .om-panel-body::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; }
151
+ .om-prompt-send:disabled { background: #2a2a4a; color: #444; cursor: not-allowed; }
178
152
 
179
153
  /* \u2500\u2500 Settings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
180
- .om-settings { display: flex; flex-direction: column; gap: 14px; }
154
+ .om-settings { display: flex; flex-direction: column; gap: 12px; }
181
155
 
182
156
  .om-field { display: flex; flex-direction: column; gap: 5px; }
183
- .om-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: #666; }
157
+ .om-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: #555; }
184
158
 
185
159
  .om-select, .om-input {
186
160
  background: rgba(255,255,255,0.04);
187
161
  border: 1px solid rgba(255,255,255,0.08);
188
162
  border-radius: 8px;
189
- padding: 9px 11px;
163
+ padding: 8px 10px;
190
164
  color: #e0e0e0;
191
165
  font-size: 13px;
192
166
  font-family: inherit;
@@ -195,130 +169,126 @@
195
169
  transition: border-color 0.15s;
196
170
  }
197
171
  .om-select:focus, .om-input:focus { border-color: rgba(108, 92, 231, 0.4); }
198
- .om-select option { background: #151528; color: #e0e0e0; }
172
+ .om-select option { background: #111125; color: #e0e0e0; }
199
173
 
200
174
  .om-key-row { display: flex; gap: 6px; align-items: stretch; }
201
175
  .om-key-input { flex: 1; min-width: 0; -webkit-text-security: disc; }
202
176
 
203
177
  .om-btn-get-key {
204
178
  display: flex; align-items: center; gap: 4px;
205
- padding: 7px 10px; background: rgba(108, 92, 231, 0.1);
206
- border: 1px solid rgba(108, 92, 231, 0.2); border-radius: 8px;
179
+ padding: 6px 9px; background: rgba(108, 92, 231, 0.08);
180
+ border: 1px solid rgba(108, 92, 231, 0.15); border-radius: 8px;
207
181
  color: #a29bfe; font-size: 11px; font-weight: 600;
208
182
  font-family: inherit; cursor: pointer; white-space: nowrap;
209
183
  transition: all 0.15s;
210
184
  }
211
- .om-btn-get-key:hover { background: rgba(108, 92, 231, 0.18); color: #c4b5fd; }
185
+ .om-btn-get-key:hover { background: rgba(108, 92, 231, 0.15); color: #c4b5fd; }
212
186
 
213
187
  .om-btn {
214
188
  display: flex; align-items: center; justify-content: center; gap: 6px;
215
189
  background: #6c5ce7; border: none; color: white; cursor: pointer;
216
- padding: 9px 16px; border-radius: 8px;
190
+ padding: 8px 14px; border-radius: 8px;
217
191
  font-size: 13px; font-weight: 600; font-family: inherit;
218
192
  transition: background 0.15s;
219
193
  }
220
194
  .om-btn:hover { background: #7c6cf7; }
221
195
  .om-btn:disabled { background: #2a2a4a; color: #555; cursor: not-allowed; }
222
-
223
196
  .om-btn-saving { background: #4a3db0; }
224
197
  .om-btn-saved { background: #00b894; }
225
198
 
226
- .om-status { font-size: 11px; padding: 6px 10px; border-radius: 6px; text-align: center; display: flex; align-items: center; justify-content: center; gap: 5px; }
227
- .om-status-success { background: rgba(0, 184, 148, 0.08); color: #00b894; }
228
- .om-status-error { background: rgba(233, 69, 96, 0.08); color: #e94560; }
199
+ .om-status { font-size: 11px; padding: 5px 8px; border-radius: 6px; text-align: center; display: flex; align-items: center; justify-content: center; gap: 4px; }
200
+ .om-status-success { background: rgba(0, 184, 148, 0.06); color: #00b894; }
201
+ .om-status-error { background: rgba(233, 69, 96, 0.06); color: #e94560; }
229
202
 
230
- .om-key-hint { font-size: 10px; color: #555; margin-top: 4px; line-height: 1.4; }
203
+ .om-key-hint { font-size: 10px; color: #444; margin-top: 3px; }
231
204
  .om-key-hint a { color: #7c6cf7; cursor: pointer; text-decoration: none; }
232
205
  .om-key-hint a:hover { text-decoration: underline; }
233
206
 
234
207
  .om-update-banner {
235
208
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
236
- padding: 8px 12px; margin-bottom: 12px;
237
- background: rgba(253, 203, 110, 0.06); border: 1px solid rgba(253, 203, 110, 0.15);
238
- border-radius: 8px; font-size: 12px; color: #fdcb6e;
209
+ padding: 7px 10px; margin-bottom: 10px;
210
+ background: rgba(253, 203, 110, 0.04); border: 1px solid rgba(253, 203, 110, 0.12);
211
+ border-radius: 8px; font-size: 11px; color: #fdcb6e;
239
212
  }
240
213
  .om-update-cmd {
241
- display: block; width: 100%; margin-top: 3px;
242
- padding: 5px 8px; background: rgba(0, 0, 0, 0.15); border-radius: 5px;
214
+ display: block; width: 100%; margin-top: 2px;
215
+ padding: 4px 7px; background: rgba(0, 0, 0, 0.12); border-radius: 4px;
243
216
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
244
217
  font-size: 11px; color: #fdcb6e; user-select: all;
245
218
  }
246
219
 
247
220
  /* \u2500\u2500 Chat \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
248
221
  .om-chat-messages {
249
- display: flex; flex-direction: column; gap: 10px;
250
- min-height: 120px; max-height: 400px;
251
- overflow-y: auto; padding-bottom: 6px;
222
+ display: flex; flex-direction: column; gap: 8px;
223
+ max-height: 380px;
224
+ overflow-y: auto;
252
225
  }
253
226
  .om-chat-messages::-webkit-scrollbar { width: 4px; }
254
- .om-chat-messages::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 2px; }
227
+ .om-chat-messages::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.06); border-radius: 2px; }
255
228
 
256
229
  .om-msg {
257
- padding: 9px 12px; border-radius: 10px;
258
- font-size: 13px; line-height: 1.55;
230
+ padding: 8px 11px; border-radius: 10px;
231
+ font-size: 13px; line-height: 1.5;
259
232
  white-space: pre-wrap; word-break: break-word;
260
233
  }
261
- .om-msg-user { background: rgba(108, 92, 231, 0.1); color: #d0d0d0; margin-left: 40px; border-bottom-right-radius: 3px; }
262
- .om-msg-assistant { background: rgba(255,255,255,0.02); color: #bbb; margin-right: 40px; border-bottom-left-radius: 3px; border: 1px solid rgba(255,255,255,0.04); }
263
- .om-msg-system { background: rgba(108, 92, 231, 0.06); color: #a29bfe; font-size: 11px; text-align: center; padding: 6px 8px; border-radius: 6px; }
234
+ .om-msg-user { background: rgba(108, 92, 231, 0.08); color: #ccc; margin-left: 36px; border-bottom-right-radius: 3px; }
235
+ .om-msg-assistant { background: rgba(255,255,255,0.02); color: #aaa; margin-right: 36px; border-bottom-left-radius: 3px; border: 1px solid rgba(255,255,255,0.03); }
236
+ .om-msg-system { background: rgba(108, 92, 231, 0.05); color: #888; font-size: 11px; text-align: center; padding: 5px 8px; border-radius: 6px; }
264
237
 
265
- .om-chat-empty { color: #3a3a5a; text-align: center; padding: 40px 20px; font-size: 13px; line-height: 1.6; }
238
+ .om-chat-empty { color: #333; text-align: center; padding: 32px 16px; font-size: 12px; line-height: 1.6; }
266
239
 
267
- .om-spinner { width: 14px; height: 14px; border: 2px solid rgba(108,92,231,0.15); border-top-color: #6c5ce7; border-radius: 50%; animation: om-spin 0.6s linear infinite; display: inline-block; vertical-align: -2px; margin-right: 6px; }
240
+ .om-spinner { width: 12px; height: 12px; border: 2px solid rgba(108,92,231,0.12); border-top-color: #6c5ce7; border-radius: 50%; animation: om-spin 0.6s linear infinite; display: inline-block; vertical-align: -1px; margin-right: 5px; }
268
241
  @keyframes om-spin { to { transform: rotate(360deg); } }
269
242
 
270
- /* \u2500\u2500 Element info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
271
243
  .om-element-info {
272
- background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.04);
273
- border-radius: 6px; padding: 8px 10px;
244
+ background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.03);
245
+ border-radius: 6px; padding: 6px 8px;
274
246
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
275
- font-size: 10px; color: #666; max-height: 80px; overflow-y: auto; margin-bottom: 8px;
247
+ font-size: 10px; color: #555; max-height: 60px; overflow-y: auto; margin-bottom: 6px;
276
248
  }
277
- `;var p=null,m=new Map,ge=[],N=[],E=!1,P=null;function _(){return Math.random().toString(36).slice(2)+Date.now().toString(36)}function O(e,t){return new Promise((o,n)=>{try{p=new WebSocket(`ws://127.0.0.1:${e}/__openmagic__/ws`),p.onopen=()=>{let i=_();p.send(JSON.stringify({id:i,type:"handshake",payload:{token:t}})),m.set(i,s=>{if(s.type==="handshake.ok"){E=!0;for(let r of N)p?.send(r);N=[],o()}else s.type==="error"&&n(new Error(s.payload?.message||"Handshake failed"))})},p.onmessage=i=>{try{let s=JSON.parse(i.data);s.id&&m.has(s.id)&&(m.get(s.id)(s),(s.type==="llm.done"||s.type==="llm.error"||!s.type.startsWith("llm."))&&m.delete(s.id));for(let r of ge)r(s)}catch{}},p.onclose=()=>{E=!1,P||(P=setTimeout(()=>{P=null,O(e,t).catch(()=>{})},2e3))},p.onerror=()=>{}}catch(i){n(i)}})}function q(e){let t=JSON.stringify(e);p&&p.readyState===WebSocket.OPEN&&E?p.send(t):N.push(t)}function w(e,t){return new Promise((o,n)=>{let i=_(),s=setTimeout(()=>{m.delete(i),n(new Error("Request timeout"))},3e4);m.set(i,r=>{clearTimeout(s),r.type==="error"?n(new Error(r.payload?.message||"Unknown error")):o(r)}),q({id:i,type:e,payload:t})})}function B(e,t,o){return new Promise((n,i)=>{let s=_(),r=setTimeout(()=>{m.delete(s),i(new Error("Stream timeout"))},12e4);m.set(s,l=>{l.type==="llm.chunk"?o(l.payload?.delta||""):l.type==="llm.done"?(clearTimeout(r),m.delete(s),n(l.payload)):(l.type==="llm.error"||l.type==="error")&&(clearTimeout(r),m.delete(s),i(new Error(l.payload?.message||"Stream error")))}),q({id:s,type:e,payload:t})})}function z(){return E}var fe=["display","position","width","height","margin","padding","color","background-color","background","font-size","font-weight","font-family","border","border-radius","box-shadow","flex-direction","justify-content","align-items","gap","grid-template-columns","grid-template-rows","overflow","opacity","z-index","text-align","line-height","letter-spacing"];function U(e){let t=window.getComputedStyle(e),o={};for(let i of fe)o[i]=t.getPropertyValue(i);let n=e.getBoundingClientRect();return{tagName:e.tagName.toLowerCase(),id:e.id||"",className:e.className||"",textContent:(e.textContent||"").trim().slice(0,200),outerHTML:be(e),cssSelector:ye(e),xpath:xe(e),computedStyles:o,rect:{x:n.x,y:n.y,width:n.width,height:n.height}}}function be(e){let t=e.cloneNode(!0);t.querySelectorAll("script, style, svg").forEach(i=>i.remove());let n=t.outerHTML;if(n.length>2e3){let i=e.tagName.toLowerCase(),s=Array.from(e.attributes).map(l=>`${l.name}="${l.value}"`).join(" "),r=Array.from(e.children).slice(0,5).map(l=>`<${l.tagName.toLowerCase()} .../>`).join(`
249
+ `;var p=null,m=new Map,me=[],$=[],L=!1,H=null;function P(){return Math.random().toString(36).slice(2)+Date.now().toString(36)}function N(e,t){return new Promise((o,n)=>{try{p=new WebSocket(`ws://127.0.0.1:${e}/__openmagic__/ws`),p.onopen=()=>{let i=P();p.send(JSON.stringify({id:i,type:"handshake",payload:{token:t}})),m.set(i,s=>{if(s.type==="handshake.ok"){L=!0;for(let r of $)p?.send(r);$=[],o()}else s.type==="error"&&n(new Error(s.payload?.message||"Handshake failed"))})},p.onmessage=i=>{try{let s=JSON.parse(i.data);s.id&&m.has(s.id)&&(m.get(s.id)(s),(s.type==="llm.done"||s.type==="llm.error"||!s.type.startsWith("llm."))&&m.delete(s.id));for(let r of me)r(s)}catch{}},p.onclose=()=>{L=!1,H||(H=setTimeout(()=>{H=null,N(e,t).catch(()=>{})},2e3))},p.onerror=()=>{}}catch(i){n(i)}})}function q(e){let t=JSON.stringify(e);p&&p.readyState===WebSocket.OPEN&&L?p.send(t):$.push(t)}function v(e,t){return new Promise((o,n)=>{let i=P(),s=setTimeout(()=>{m.delete(i),n(new Error("Request timeout"))},3e4);m.set(i,r=>{clearTimeout(s),r.type==="error"?n(new Error(r.payload?.message||"Unknown error")):o(r)}),q({id:i,type:e,payload:t})})}function B(e,t,o){return new Promise((n,i)=>{let s=P(),r=setTimeout(()=>{m.delete(s),i(new Error("Stream timeout"))},12e4);m.set(s,l=>{l.type==="llm.chunk"?o(l.payload?.delta||""):l.type==="llm.done"?(clearTimeout(r),m.delete(s),n(l.payload)):(l.type==="llm.error"||l.type==="error")&&(clearTimeout(r),m.delete(s),i(new Error(l.payload?.message||"Stream error")))}),q({id:s,type:e,payload:t})})}function U(){return L}var ge=["display","position","width","height","margin","padding","color","background-color","background","font-size","font-weight","font-family","border","border-radius","box-shadow","flex-direction","justify-content","align-items","gap","grid-template-columns","grid-template-rows","overflow","opacity","z-index","text-align","line-height","letter-spacing"];function z(e){let t=window.getComputedStyle(e),o={};for(let i of ge)o[i]=t.getPropertyValue(i);let n=e.getBoundingClientRect();return{tagName:e.tagName.toLowerCase(),id:e.id||"",className:e.className||"",textContent:(e.textContent||"").trim().slice(0,200),outerHTML:he(e),cssSelector:fe(e),xpath:be(e),computedStyles:o,rect:{x:n.x,y:n.y,width:n.width,height:n.height}}}function he(e){let t=e.cloneNode(!0);t.querySelectorAll("script, style, svg").forEach(i=>i.remove());let n=t.outerHTML;if(n.length>2e3){let i=e.tagName.toLowerCase(),s=Array.from(e.attributes).map(l=>`${l.name}="${l.value}"`).join(" "),r=Array.from(e.children).slice(0,5).map(l=>`<${l.tagName.toLowerCase()} .../>`).join(`
278
250
  `);n=`<${i} ${s}>
279
251
  ${r}
280
252
  ${e.children.length>5?`<!-- +${e.children.length-5} more children -->`:""}
281
- </${i}>`}return n}function ye(e){if(e.id)return`#${e.id}`;let t=[],o=e;for(;o&&o!==document.body;){let n=o.tagName.toLowerCase();if(o.id){t.unshift(`#${o.id}`);break}if(o.className&&typeof o.className=="string"){let s=o.className.trim().split(/\s+/).filter(r=>!r.startsWith("__")&&r.length<30).slice(0,2);s.length>0&&(n+="."+s.join("."))}let i=o.parentElement;if(i){let s=Array.from(i.children).filter(r=>r.tagName===o.tagName);if(s.length>1){let r=s.indexOf(o)+1;n+=`:nth-child(${r})`}}t.unshift(n),o=o.parentElement}return t.join(" > ")}function xe(e){let t=[],o=e;for(;o&&o!==document;){if(o.nodeType===Node.ELEMENT_NODE){let n=o,i=1,s=n.previousElementSibling;for(;s;)s.tagName===n.tagName&&i++,s=s.previousElementSibling;t.unshift(`${n.tagName.toLowerCase()}[${i}]`)}o=o.parentNode}return"/"+t.join("/")}var d=null;function G(e){d||(d=document.createElement("div"),d.style.cssText=`
253
+ </${i}>`}return n}function fe(e){if(e.id)return`#${e.id}`;let t=[],o=e;for(;o&&o!==document.body;){let n=o.tagName.toLowerCase();if(o.id){t.unshift(`#${o.id}`);break}if(o.className&&typeof o.className=="string"){let s=o.className.trim().split(/\s+/).filter(r=>!r.startsWith("__")&&r.length<30).slice(0,2);s.length>0&&(n+="."+s.join("."))}let i=o.parentElement;if(i){let s=Array.from(i.children).filter(r=>r.tagName===o.tagName);if(s.length>1){let r=s.indexOf(o)+1;n+=`:nth-child(${r})`}}t.unshift(n),o=o.parentElement}return t.join(" > ")}function be(e){let t=[],o=e;for(;o&&o!==document;){if(o.nodeType===Node.ELEMENT_NODE){let n=o,i=1,s=n.previousElementSibling;for(;s;)s.tagName===n.tagName&&i++,s=s.previousElementSibling;t.unshift(`${n.tagName.toLowerCase()}[${i}]`)}o=o.parentNode}return"/"+t.join("/")}var d=null;function G(e){d||(d=document.createElement("div"),d.style.cssText=`
282
254
  position: fixed;
283
255
  pointer-events: none;
284
256
  z-index: 2147483646;
285
257
  border: 2px solid #6c5ce7;
286
258
  background: rgba(108, 92, 231, 0.1);
287
259
  transition: all 0.1s ease;
288
- `,d.dataset.openmagic="highlight",document.body.appendChild(d)),d.style.left=`${e.x}px`,d.style.top=`${e.y}px`,d.style.width=`${e.width}px`,d.style.height=`${e.height}px`,d.style.display="block"}function I(){d&&(d.style.display="none")}async function j(e){try{return e?await we(e):await ve()}catch(t){return console.warn("[OpenMagic] Screenshot capture failed:",t),null}}async function ve(){let e=document.createElement("canvas"),t=window.devicePixelRatio||1;e.width=window.innerWidth*t,e.height=window.innerHeight*t;let o=e.getContext("2d");o.scale(t,t);try{let n=await K(document.body),i=await F(n,window.innerWidth,window.innerHeight);return o.drawImage(i,0,0),e.toDataURL("image/png")}catch{return null}}async function we(e){let t=e.getBoundingClientRect(),o=document.createElement("canvas"),n=window.devicePixelRatio||1;o.width=t.width*n,o.height=t.height*n;let i=o.getContext("2d");i.scale(n,n);try{let s=await K(e),r=await F(s,t.width,t.height);return i.drawImage(r,0,0),o.toDataURL("image/png")}catch{return null}}function K(e){return new Promise(t=>{let o=e.cloneNode(!0);V(e,o);let n=e.getBoundingClientRect(),i=n.width,s=n.height,r=`
260
+ `,d.dataset.openmagic="highlight",document.body.appendChild(d)),d.style.left=`${e.x}px`,d.style.top=`${e.y}px`,d.style.width=`${e.width}px`,d.style.height=`${e.height}px`,d.style.display="block"}function I(){d&&(d.style.display="none")}async function K(e){try{return e?await xe(e):await ye()}catch(t){return console.warn("[OpenMagic] Screenshot capture failed:",t),null}}async function ye(){let e=document.createElement("canvas"),t=window.devicePixelRatio||1;e.width=window.innerWidth*t,e.height=window.innerHeight*t;let o=e.getContext("2d");o.scale(t,t);try{let n=await j(document.body),i=await F(n,window.innerWidth,window.innerHeight);return o.drawImage(i,0,0),e.toDataURL("image/png")}catch{return null}}async function xe(e){let t=e.getBoundingClientRect(),o=document.createElement("canvas"),n=window.devicePixelRatio||1;o.width=t.width*n,o.height=t.height*n;let i=o.getContext("2d");i.scale(n,n);try{let s=await j(e),r=await F(s,t.width,t.height);return i.drawImage(r,0,0),o.toDataURL("image/png")}catch{return null}}function j(e){return new Promise(t=>{let o=e.cloneNode(!0);V(e,o);let n=e.getBoundingClientRect(),i=n.width,s=n.height,r=`
289
261
  <svg xmlns="http://www.w3.org/2000/svg" width="${i}" height="${s}">
290
262
  <foreignObject width="100%" height="100%">
291
263
  <div xmlns="http://www.w3.org/1999/xhtml" style="width:${i}px;height:${s}px;overflow:hidden;">
292
264
  ${o.outerHTML}
293
265
  </div>
294
266
  </foreignObject>
295
- </svg>`;t(r)})}function V(e,t){let o=window.getComputedStyle(e),n="";for(let r=0;r<o.length;r++){let l=o[r];n+=`${l}:${o.getPropertyValue(l)};`}t.style.cssText=n;let i=e.children,s=t.children;for(let r=0;r<i.length&&r<s.length;r++)V(i[r],s[r])}function F(e,t,o){return new Promise((n,i)=>{let s=new Image,r=new Blob([e],{type:"image/svg+xml;charset=utf-8"}),l=URL.createObjectURL(r);s.onload=()=>{URL.revokeObjectURL(l),n(s)},s.onerror=()=>{URL.revokeObjectURL(l),i(new Error("Failed to load SVG image"))},s.width=t,s.height=o,s.src=l})}var T=[];var X=!1;function Y(){if(X)return;X=!0;let e=window.fetch;window.fetch=async function(...n){let i=new Request(...n),s={method:i.method,url:i.url,timestamp:Date.now()};try{let r=await e.apply(this,n);return s.status=r.status,s.duration=Date.now()-s.timestamp,R(s),r}catch(r){throw s.status=0,s.duration=Date.now()-s.timestamp,R(s),r}};let t=XMLHttpRequest.prototype.open,o=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.open=function(n,i,...s){return this.__om_method=n,this.__om_url=i,this.__om_start=Date.now(),t.apply(this,[n,i,...s])},XMLHttpRequest.prototype.send=function(...n){return this.addEventListener("loadend",()=>{R({method:this.__om_method||"GET",url:this.__om_url||"",status:this.status,duration:Date.now()-(this.__om_start||Date.now()),timestamp:this.__om_start||Date.now()})}),o.apply(this,n)}}function R(e){e.url.includes("__openmagic__")||(T.push(e),T.length>50&&T.shift())}function ke(){return[...T]}var C=[],Se=100,W=!1;function J(){if(W)return;W=!0;let e=["log","warn","error","info","debug"];for(let t of e){let o=console[t];console[t]=function(...n){C.push({level:t,args:n.map(i=>{try{return typeof i=="object"?JSON.stringify(i).slice(0,500):String(i)}catch{return String(i)}}),timestamp:Date.now()}),C.length>Se&&C.shift(),o.apply(console,n)}}}function Le(){return[...C]}function Q(e,t){return{selectedElement:e?{tagName:e.tagName,id:e.id,className:e.className,textContent:e.textContent,outerHTML:e.outerHTML,cssSelector:e.cssSelector,computedStyles:e.computedStyles}:void 0,screenshot:t||void 0,networkLogs:ke().map(o=>({method:o.method,url:o.url,status:o.status,duration:o.duration,timestamp:o.timestamp})),consoleLogs:Le().map(o=>({level:o.level,args:o.args,timestamp:o.timestamp}))}}var c={sparkle:'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.582a.5.5 0 0 1 0 .962L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/></svg>',crosshair:'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="22" y1="12" x2="18" y2="12"/><line x1="6" y1="12" x2="2" y2="12"/><line x1="12" y1="6" x2="12" y2="2"/><line x1="12" y1="22" x2="12" y2="18"/></svg>',camera:'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/></svg>',chat:'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',settings:'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>',send:'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>',x:'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',externalLink:'<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>',check:'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>',grip:'<svg width="7" height="14" viewBox="0 0 8 14" fill="currentColor"><circle cx="2" cy="2" r="1.2"/><circle cx="6" cy="2" r="1.2"/><circle cx="2" cy="7" r="1.2"/><circle cx="6" cy="7" r="1.2"/><circle cx="2" cy="12" r="1.2"/><circle cx="6" cy="12" r="1.2"/></svg>'},Z={openai:{name:"OpenAI",keyUrl:"https://platform.openai.com/api-keys",keyPlaceholder:"sk-...",models:[{id:"gpt-5.4",name:"GPT-5.4"},{id:"gpt-5.4-mini",name:"GPT-5.4 Mini"},{id:"gpt-5.2",name:"GPT-5.2 Thinking"},{id:"o3",name:"o3"},{id:"o4-mini",name:"o4-mini"},{id:"gpt-4.1",name:"GPT-4.1"},{id:"gpt-4.1-mini",name:"GPT-4.1 Mini"}]},anthropic:{name:"Anthropic",keyUrl:"https://console.anthropic.com/settings/keys",keyPlaceholder:"sk-ant-...",models:[{id:"claude-opus-4-6",name:"Claude Opus 4.6"},{id:"claude-sonnet-4-6",name:"Claude Sonnet 4.6"},{id:"claude-haiku-4-5-20251001",name:"Claude Haiku 4.5"}]},google:{name:"Google Gemini",keyUrl:"https://aistudio.google.com/apikey",keyPlaceholder:"AIza...",models:[{id:"gemini-3.1-pro-preview",name:"Gemini 3.1 Pro"},{id:"gemini-3-flash-preview",name:"Gemini 3 Flash"},{id:"gemini-2.5-pro",name:"Gemini 2.5 Pro"},{id:"gemini-2.5-flash",name:"Gemini 2.5 Flash"}]},xai:{name:"xAI (Grok)",keyUrl:"https://console.x.ai/team/default/api-keys",keyPlaceholder:"xai-...",models:[{id:"grok-4.20-0309-reasoning",name:"Grok 4.20 Reasoning"},{id:"grok-4-1-fast-non-reasoning",name:"Grok 4.1 Fast"}]},deepseek:{name:"DeepSeek",keyUrl:"https://platform.deepseek.com/api_keys",keyPlaceholder:"sk-...",models:[{id:"deepseek-chat",name:"DeepSeek V3.2"},{id:"deepseek-reasoner",name:"DeepSeek R1"}]},mistral:{name:"Mistral",keyUrl:"https://console.mistral.ai/api-keys",keyPlaceholder:"...",models:[{id:"mistral-large-3-25-12",name:"Mistral Large 3"},{id:"codestral-2508",name:"Codestral"},{id:"devstral-2-25-12",name:"Devstral 2"}]},groq:{name:"Groq",keyUrl:"https://console.groq.com/keys",keyPlaceholder:"gsk_...",models:[{id:"meta-llama/llama-4-scout-17b-16e-instruct",name:"Llama 4 Scout"},{id:"llama-3.3-70b-versatile",name:"Llama 3.3 70B"}]},minimax:{name:"MiniMax",keyUrl:"https://platform.minimax.chat/user-center/basic-information/interface-key",keyPlaceholder:"MiniMax key...",models:[{id:"MiniMax-M2.7",name:"MiniMax M2.7"},{id:"MiniMax-M2.5",name:"MiniMax M2.5"}]},moonshot:{name:"Kimi (Moonshot)",keyUrl:"https://platform.moonshot.cn/console/api-keys",keyPlaceholder:"Moonshot key...",models:[{id:"kimi-k2.5",name:"Kimi K2.5"},{id:"kimi-k2-thinking",name:"Kimi K2 Thinking"}]},qwen:{name:"Qwen (Alibaba)",keyUrl:"https://dashscope.console.aliyun.com/apiKey",keyPlaceholder:"DashScope key...",models:[{id:"qwen3.5-plus",name:"Qwen 3.5 Plus"},{id:"qwen-max",name:"Qwen Max"}]},zhipu:{name:"Zhipu AI (GLM)",keyUrl:"https://open.bigmodel.cn/usercenter/apikeys",keyPlaceholder:"Zhipu key...",models:[{id:"glm-5",name:"GLM-5"},{id:"glm-4.7",name:"GLM-4.7"}]},doubao:{name:"Doubao (ByteDance)",keyUrl:"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey",keyPlaceholder:"Volcano key...",models:[{id:"doubao-seed-2-0-pro",name:"Doubao Seed 2.0 Pro"},{id:"doubao-seed-2-0-code",name:"Doubao Seed 2.0 Code"}]},ollama:{name:"Ollama (Local)",keyPlaceholder:"not required",local:!0,models:[]},openrouter:{name:"OpenRouter",keyUrl:"https://openrouter.ai/settings/keys",keyPlaceholder:"sk-or-...",models:[]}},ae="0.8.2",a={connected:!1,panelOpen:!1,activePanel:"",selecting:!1,selectedElement:null,screenshot:null,messages:[],streaming:!1,streamContent:"",provider:"",model:"",hasApiKey:!1,roots:[],updateAvailable:!1,latestVersion:"",saveStatus:""},f,u,k,x,se,g,h;function ee(){if(document.querySelector("openmagic-toolbar"))return;let e=document.createElement("openmagic-toolbar");e.dataset.openmagic="true",f=e.attachShadow({mode:"closed"});let t=document.createElement("style");t.textContent=A,f.appendChild(t);let o=document.createElement("div");f.appendChild(o),o.innerHTML=Me(),u=o.querySelector(".om-pill"),k=o.querySelector(".om-prompt-bar"),x=o.querySelector(".om-prompt-input"),se=o.querySelector(".om-prompt-context"),g=o.querySelector(".om-panel"),h=o.querySelector(".om-panel-body"),document.body.appendChild(e),Ee(o),Oe(),Y(),J(),Re();let n=window.__OPENMAGIC_CONFIG__;n&&O(n.wsPort,n.token).then(()=>(a.connected=!0,te(),w("config.get"))).then(i=>{a.provider=i.payload?.provider||"",a.model=i.payload?.model||"",a.hasApiKey=i.payload?.hasApiKey||!1,a.roots=i.payload?.roots||[],(!a.provider||!a.hasApiKey)&&v("settings"),M()}).catch(()=>{a.connected=!1,te()})}function Me(){return`
296
- <div class="om-panel om-hidden">
297
- <div class="om-panel-header">
298
- <span class="om-panel-title"></span>
299
- <span class="om-panel-version">v${ae}</span>
300
- <button class="om-panel-close" data-action="close-panel">${c.x}</button>
267
+ </svg>`;t(r)})}function V(e,t){let o=window.getComputedStyle(e),n="";for(let r=0;r<o.length;r++){let l=o[r];n+=`${l}:${o.getPropertyValue(l)};`}t.style.cssText=n;let i=e.children,s=t.children;for(let r=0;r<i.length&&r<s.length;r++)V(i[r],s[r])}function F(e,t,o){return new Promise((n,i)=>{let s=new Image,r=new Blob([e],{type:"image/svg+xml;charset=utf-8"}),l=URL.createObjectURL(r);s.onload=()=>{URL.revokeObjectURL(l),n(s)},s.onerror=()=>{URL.revokeObjectURL(l),i(new Error("Failed to load SVG image"))},s.width=t,s.height=o,s.src=l})}var M=[];var X=!1;function Y(){if(X)return;X=!0;let e=window.fetch;window.fetch=async function(...n){let i=new Request(...n),s={method:i.method,url:i.url,timestamp:Date.now()};try{let r=await e.apply(this,n);return s.status=r.status,s.duration=Date.now()-s.timestamp,_(s),r}catch(r){throw s.status=0,s.duration=Date.now()-s.timestamp,_(s),r}};let t=XMLHttpRequest.prototype.open,o=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.open=function(n,i,...s){return this.__om_method=n,this.__om_url=i,this.__om_start=Date.now(),t.apply(this,[n,i,...s])},XMLHttpRequest.prototype.send=function(...n){return this.addEventListener("loadend",()=>{_({method:this.__om_method||"GET",url:this.__om_url||"",status:this.status,duration:Date.now()-(this.__om_start||Date.now()),timestamp:this.__om_start||Date.now()})}),o.apply(this,n)}}function _(e){e.url.includes("__openmagic__")||(M.push(e),M.length>50&&M.shift())}function ve(){return[...M]}var E=[],we=100,W=!1;function J(){if(W)return;W=!0;let e=["log","warn","error","info","debug"];for(let t of e){let o=console[t];console[t]=function(...n){E.push({level:t,args:n.map(i=>{try{return typeof i=="object"?JSON.stringify(i).slice(0,500):String(i)}catch{return String(i)}}),timestamp:Date.now()}),E.length>we&&E.shift(),o.apply(console,n)}}}function ke(){return[...E]}function Q(e,t){return{selectedElement:e?{tagName:e.tagName,id:e.id,className:e.className,textContent:e.textContent,outerHTML:e.outerHTML,cssSelector:e.cssSelector,computedStyles:e.computedStyles}:void 0,screenshot:t||void 0,networkLogs:ve().map(o=>({method:o.method,url:o.url,status:o.status,duration:o.duration,timestamp:o.timestamp})),consoleLogs:ke().map(o=>({level:o.level,args:o.args,timestamp:o.timestamp}))}}var c={sparkle:'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.582a.5.5 0 0 1 0 .962L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/></svg>',crosshair:'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="22" y1="12" x2="18" y2="12"/><line x1="6" y1="12" x2="2" y2="12"/><line x1="12" y1="6" x2="12" y2="2"/><line x1="12" y1="22" x2="12" y2="18"/></svg>',camera:'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/></svg>',chat:'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',settings:'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>',send:'<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>',x:'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',externalLink:'<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>',check:'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>',grip:'<svg width="7" height="14" viewBox="0 0 8 14" fill="currentColor"><circle cx="2" cy="2" r="1.2"/><circle cx="6" cy="2" r="1.2"/><circle cx="2" cy="7" r="1.2"/><circle cx="6" cy="7" r="1.2"/><circle cx="2" cy="12" r="1.2"/><circle cx="6" cy="12" r="1.2"/></svg>'},Z={openai:{name:"OpenAI",keyUrl:"https://platform.openai.com/api-keys",keyPlaceholder:"sk-...",models:[{id:"gpt-5.4",name:"GPT-5.4"},{id:"gpt-5.4-mini",name:"GPT-5.4 Mini"},{id:"gpt-5.2",name:"GPT-5.2 Thinking"},{id:"o3",name:"o3"},{id:"o4-mini",name:"o4-mini"},{id:"gpt-4.1",name:"GPT-4.1"},{id:"gpt-4.1-mini",name:"GPT-4.1 Mini"}]},anthropic:{name:"Anthropic",keyUrl:"https://console.anthropic.com/settings/keys",keyPlaceholder:"sk-ant-...",models:[{id:"claude-opus-4-6",name:"Claude Opus 4.6"},{id:"claude-sonnet-4-6",name:"Claude Sonnet 4.6"},{id:"claude-haiku-4-5-20251001",name:"Claude Haiku 4.5"}]},google:{name:"Google Gemini",keyUrl:"https://aistudio.google.com/apikey",keyPlaceholder:"AIza...",models:[{id:"gemini-3.1-pro-preview",name:"Gemini 3.1 Pro"},{id:"gemini-3-flash-preview",name:"Gemini 3 Flash"},{id:"gemini-2.5-pro",name:"Gemini 2.5 Pro"},{id:"gemini-2.5-flash",name:"Gemini 2.5 Flash"}]},xai:{name:"xAI (Grok)",keyUrl:"https://console.x.ai/team/default/api-keys",keyPlaceholder:"xai-...",models:[{id:"grok-4.20-0309-reasoning",name:"Grok 4.20 Reasoning"},{id:"grok-4-1-fast-non-reasoning",name:"Grok 4.1 Fast"}]},deepseek:{name:"DeepSeek",keyUrl:"https://platform.deepseek.com/api_keys",keyPlaceholder:"sk-...",models:[{id:"deepseek-chat",name:"DeepSeek V3.2"},{id:"deepseek-reasoner",name:"DeepSeek R1"}]},mistral:{name:"Mistral",keyUrl:"https://console.mistral.ai/api-keys",keyPlaceholder:"...",models:[{id:"mistral-large-3-25-12",name:"Mistral Large 3"},{id:"codestral-2508",name:"Codestral"},{id:"devstral-2-25-12",name:"Devstral 2"}]},groq:{name:"Groq",keyUrl:"https://console.groq.com/keys",keyPlaceholder:"gsk_...",models:[{id:"meta-llama/llama-4-scout-17b-16e-instruct",name:"Llama 4 Scout"},{id:"llama-3.3-70b-versatile",name:"Llama 3.3 70B"}]},minimax:{name:"MiniMax",keyUrl:"https://platform.minimax.chat/user-center/basic-information/interface-key",keyPlaceholder:"MiniMax key...",models:[{id:"MiniMax-M2.7",name:"MiniMax M2.7"},{id:"MiniMax-M2.5",name:"MiniMax M2.5"}]},moonshot:{name:"Kimi (Moonshot)",keyUrl:"https://platform.moonshot.cn/console/api-keys",keyPlaceholder:"Moonshot key...",models:[{id:"kimi-k2.5",name:"Kimi K2.5"},{id:"kimi-k2-thinking",name:"Kimi K2 Thinking"}]},qwen:{name:"Qwen (Alibaba)",keyUrl:"https://dashscope.console.aliyun.com/apiKey",keyPlaceholder:"DashScope key...",models:[{id:"qwen3.5-plus",name:"Qwen 3.5 Plus"},{id:"qwen-max",name:"Qwen Max"}]},zhipu:{name:"Zhipu AI (GLM)",keyUrl:"https://open.bigmodel.cn/usercenter/apikeys",keyPlaceholder:"Zhipu key...",models:[{id:"glm-5",name:"GLM-5"},{id:"glm-4.7",name:"GLM-4.7"}]},doubao:{name:"Doubao (ByteDance)",keyUrl:"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey",keyPlaceholder:"Volcano key...",models:[{id:"doubao-seed-2-0-pro",name:"Doubao Seed 2.0 Pro"},{id:"doubao-seed-2-0-code",name:"Doubao Seed 2.0 Code"}]},ollama:{name:"Ollama (Local)",keyPlaceholder:"not required",local:!0,models:[]},openrouter:{name:"OpenRouter",keyUrl:"https://openrouter.ai/settings/keys",keyPlaceholder:"sk-or-...",models:[]}},Se="0.9.0",a={connected:!1,panelOpen:!1,activePanel:"",selecting:!1,selectedElement:null,screenshot:null,messages:[],streaming:!1,streamContent:"",provider:"",model:"",hasApiKey:!1,roots:[],updateAvailable:!1,latestVersion:"",saveStatus:""},g,h,y,ae,A,u;function ee(){if(document.querySelector("openmagic-toolbar"))return;let e=document.createElement("openmagic-toolbar");e.dataset.openmagic="true",g=e.attachShadow({mode:"closed"});let t=document.createElement("style");t.textContent=D,g.appendChild(t);let o=document.createElement("div");g.appendChild(o),o.innerHTML=Le(),h=o.querySelector(".om-toolbar"),y=o.querySelector(".om-prompt-input"),ae=o.querySelector(".om-prompt-context"),A=o.querySelector(".om-panel"),u=o.querySelector(".om-panel-body"),document.body.appendChild(e),Me(o),_e(),Y(),J(),Oe();let n=window.__OPENMAGIC_CONFIG__;n&&N(n.wsPort,n.token).then(()=>(a.connected=!0,te(),v("config.get"))).then(i=>{a.provider=i.payload?.provider||"",a.model=i.payload?.model||"",a.hasApiKey=i.payload?.hasApiKey||!1,a.roots=i.payload?.roots||[],(!a.provider||!a.hasApiKey)&&x("settings"),S()}).catch(()=>{a.connected=!1,te()})}function Le(){return`
268
+ <div class="om-toolbar">
269
+ <div class="om-toolbar-header">
270
+ <span class="om-grab">${c.grip}</span>
271
+ <span class="om-pill-brand">
272
+ <span class="om-pill-icon">${c.sparkle}</span>
273
+ <span class="om-pill-text">OpenMagic</span>
274
+ </span>
275
+ <span class="om-pill-divider"></span>
276
+ <button class="om-pill-btn" data-action="select" title="Select element">${c.crosshair}</button>
277
+ <button class="om-pill-btn" data-action="screenshot" title="Screenshot">${c.camera}</button>
278
+ <span class="om-pill-divider"></span>
279
+ <button class="om-pill-btn" data-action="chat" title="Chat">${c.chat}</button>
280
+ <button class="om-pill-btn" data-action="settings" title="Settings">${c.settings}</button>
281
+ <span class="om-status-dot disconnected"></span>
282
+ </div>
283
+ <div class="om-panel om-hidden">
284
+ <div class="om-panel-body"></div>
285
+ </div>
286
+ <div class="om-prompt-row">
287
+ <div class="om-prompt-context"></div>
288
+ <input class="om-prompt-input" type="text" placeholder="Describe what to change..." autocomplete="off" />
289
+ <button class="om-prompt-send" data-action="prompt-send">${c.send}</button>
301
290
  </div>
302
- <div class="om-panel-body"></div>
303
- </div>
304
- <div class="om-prompt-bar">
305
- <div class="om-prompt-context"></div>
306
- <input class="om-prompt-input" type="text" placeholder="Describe what you want to change..." />
307
- <button class="om-prompt-send" data-action="prompt-send">${c.send}</button>
308
- </div>
309
- <div class="om-pill">
310
- <span class="om-grab">${c.grip}</span>
311
- <span class="om-pill-brand">
312
- <span class="om-pill-icon">${c.sparkle}</span>
313
- <span class="om-pill-text">OpenMagic</span>
314
- </span>
315
- <span class="om-pill-divider"></span>
316
- <button class="om-pill-btn" data-action="select" title="Select element">${c.crosshair}</button>
317
- <button class="om-pill-btn" data-action="screenshot" title="Screenshot">${c.camera}</button>
318
- <button class="om-pill-btn" data-action="chat" title="Chat">${c.chat}</button>
319
- <button class="om-pill-btn" data-action="settings" title="Settings">${c.settings}</button>
320
- <span class="om-status-dot disconnected"></span>
321
- </div>`}function Ee(e){e.addEventListener("click",t=>{let o=t.target.closest("[data-action]");if(!o)return;t.preventDefault(),t.stopPropagation();let n=o.dataset.action;Te(n,o)}),e.addEventListener("change",t=>{let o=t.target,n=o.dataset.field;n&&(n==="provider"?(a.provider=o.value,a.model="",a.saveStatus="",y()):n==="model"&&(a.model=o.value))}),x.addEventListener("keydown",t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),le())})}function Te(e,t){switch(e){case"select":Pe();break;case"screenshot":_e();break;case"chat":oe("chat");break;case"settings":oe("settings");break;case"close-panel":ie();break;case"prompt-send":le();break;case"save-settings":$e();break;case"get-key":{let o=t.dataset.url;o&&window.open(o,"_blank","noopener");break}case"clear-element":a.selectedElement=null,$();break;case"clear-screenshot":a.screenshot=null,$();break}}function te(){let e=f.querySelector(".om-status-dot");e&&(e.className=`om-status-dot ${a.connected?"connected":"disconnected"}`)}function M(){f.querySelectorAll(".om-pill-btn").forEach(e=>{let t=e.dataset.action;e.classList.toggle("active",t===a.activePanel||t==="select"&&a.selecting)})}function $(){let e=[];a.selectedElement&&e.push(`<span class="om-prompt-chip">${a.selectedElement.tagName}${a.selectedElement.id?"#"+a.selectedElement.id:""} <button class="om-prompt-chip-x" data-action="clear-element">${c.x}</button></span>`),a.screenshot&&e.push(`<span class="om-prompt-chip">Screenshot <button class="om-prompt-chip-x" data-action="clear-screenshot">${c.x}</button></span>`),se.innerHTML=e.join("")}function v(e){a.panelOpen=!0,a.activePanel=e,g.classList.remove("om-hidden");let t=f.querySelector(".om-panel-title");t.textContent=e==="settings"?"Settings":"Chat",y(),M()}function ie(){a.panelOpen=!1,a.activePanel="",g.classList.add("om-hidden"),M()}function oe(e){a.panelOpen&&a.activePanel===e?ie():v(e)}function y(){a.activePanel==="settings"?h.innerHTML=Ce():a.activePanel==="chat"&&(h.innerHTML=He(),re())}function Ce(){let e=Object.entries(Z).map(([b,ue])=>`<option value="${b}" ${a.provider===b?"selected":""}>${ue.name}</option>`).join(""),t=Z[a.provider],o=t?t.models.map(b=>`<option value="${b.id}" ${a.model===b.id?"selected":""}>${b.name}</option>`).join(""):'<option value="">Select provider first</option>',n=t?.local||!1,i=t?.keyUrl||"",s=t?.keyPlaceholder||"Enter API key...",r=a.updateAvailable?`<div class="om-update-banner">v${a.latestVersion} available <code class="om-update-cmd">npx openmagic@latest</code></div>`:"",l=a.hasApiKey?`<div class="om-status om-status-success">${c.check} Connected</div>`:"",de=a.saveStatus==="saving"?'<span class="om-spinner"></span> Saving...':a.saveStatus==="saved"?`${c.check} Saved`:"Save",pe=a.saveStatus==="saving"?"om-btn om-btn-saving":a.saveStatus==="saved"?"om-btn om-btn-saved":"om-btn",me=a.saveStatus==="saving"?"disabled":"";return`
291
+ </div>`}function Me(e){e.addEventListener("click",t=>{let o=t.target.closest("[data-action]");if(!o)return;t.preventDefault(),t.stopPropagation();let n=o.dataset.action;Ee(n,o)}),e.addEventListener("change",t=>{let o=t.target,n=o.dataset.field;n&&(n==="provider"?(a.provider=o.value,a.model="",a.saveStatus="",b()):n==="model"&&(a.model=o.value))}),y.addEventListener("keydown",t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),ie())})}function Ee(e,t){switch(e){case"select":$e();break;case"screenshot":Ne();break;case"chat":oe("chat");break;case"settings":oe("settings");break;case"close-panel":se();break;case"prompt-send":ie();break;case"save-settings":He();break;case"get-key":{let o=t.dataset.url;o&&window.open(o,"_blank","noopener");break}case"clear-element":a.selectedElement=null,C();break;case"clear-screenshot":a.screenshot=null,C();break}}function te(){let e=g.querySelector(".om-status-dot");e&&(e.className=`om-status-dot ${a.connected?"connected":"disconnected"}`)}function S(){g.querySelectorAll(".om-pill-btn").forEach(e=>{let t=e.dataset.action;e.classList.toggle("active",t===a.activePanel||t==="select"&&a.selecting)})}function C(){let e=[];a.selectedElement&&e.push(`<span class="om-prompt-chip">${a.selectedElement.tagName}${a.selectedElement.id?"#"+a.selectedElement.id:""} <button class="om-prompt-chip-x" data-action="clear-element">${c.x}</button></span>`),a.screenshot&&e.push(`<span class="om-prompt-chip">Screenshot <button class="om-prompt-chip-x" data-action="clear-screenshot">${c.x}</button></span>`),ae.innerHTML=e.join("")}function x(e){a.panelOpen=!0,a.activePanel=e,A.classList.remove("om-hidden");let t=g.querySelector(".om-panel-title");t.textContent=e==="settings"?"Settings":"Chat",b(),S()}function se(){a.panelOpen=!1,a.activePanel="",A.classList.add("om-hidden"),S()}function oe(e){a.panelOpen&&a.activePanel===e?se():x(e)}function b(){a.activePanel==="settings"?u.innerHTML=Te():a.activePanel==="chat"&&(u.innerHTML=Ce(),O())}function Te(){let e=Object.entries(Z).map(([f,pe])=>`<option value="${f}" ${a.provider===f?"selected":""}>${pe.name}</option>`).join(""),t=Z[a.provider],o=t?t.models.map(f=>`<option value="${f.id}" ${a.model===f.id?"selected":""}>${f.name}</option>`).join(""):'<option value="">Select provider first</option>',n=t?.local||!1,i=t?.keyUrl||"",s=t?.keyPlaceholder||"Enter API key...",r=a.updateAvailable?`<div class="om-update-banner">v${a.latestVersion} available <code class="om-update-cmd">npx openmagic@latest</code></div>`:"",l=a.hasApiKey?`<div class="om-status om-status-success">${c.check} Connected</div>`:"",le=a.saveStatus==="saving"?'<span class="om-spinner"></span> Saving...':a.saveStatus==="saved"?`${c.check} Saved`:"Save",ce=a.saveStatus==="saving"?"om-btn om-btn-saving":a.saveStatus==="saved"?"om-btn om-btn-saved":"om-btn",de=a.saveStatus==="saving"?"disabled":"";return`
322
292
  ${r}
323
293
  <div class="om-settings">
324
294
  <div class="om-field">
@@ -337,7 +307,7 @@
337
307
  </div>
338
308
  ${i?`<div class="om-key-hint"><a data-action="get-key" data-url="${i}">Get your ${t?.name||""} API key here</a></div>`:""}
339
309
  </div>
340
- <button class="${pe}" data-action="save-settings" ${me}>${de}</button>
310
+ <button class="${ce}" data-action="save-settings" ${de}>${le}</button>
341
311
  ${l}
342
- </div>`}function He(){if(!a.hasApiKey||!a.provider)return'<div class="om-status om-status-error">Configure your provider in Settings first</div>';let e=a.messages.map(n=>`<div class="om-msg om-msg-${n.role}">${D(n.content)}</div>`).join(""),t=a.streaming?`<div class="om-msg om-msg-assistant"><span class="om-spinner"></span>${D(a.streamContent)}</div>`:"";return`<div class="om-chat-messages">${!a.messages.length&&!a.streaming?'<div class="om-chat-empty">Select an element or type below to start</div>':""}${e}${t}</div>`}function re(){let e=h.querySelector(".om-chat-messages");e&&(e.scrollTop=e.scrollHeight)}async function $e(){let t=h.querySelector('[data-field="apiKey"]')?.value||"";if(!a.provider){a.saveStatus="error",H(),setTimeout(()=>{a.saveStatus="",y()},2e3);return}if(!z()){a.saveStatus="error",H();let n=h.querySelector('[data-action="save-settings"]');n&&(n.innerHTML="Not connected - check terminal"),setTimeout(()=>{a.saveStatus="",y()},3e3);return}let o={provider:a.provider,model:a.model};t&&(o.apiKey=t),a.saveStatus="saving",H();try{let n=await Promise.race([w("config.set",o),new Promise((i,s)=>setTimeout(()=>s(new Error("Save timed out")),8e3))]);a.hasApiKey=!!(t||a.hasApiKey),a.saveStatus="saved",H(),setTimeout(()=>{a.saveStatus="",a.activePanel==="settings"&&v("chat")},1200)}catch(n){a.saveStatus="error";let i=h.querySelector('[data-action="save-settings"]'),s=(n?.message||"").includes("timeout")?"Connection timeout - is the CLI running?":(n?.message||"").includes("connected")?"Not connected to OpenMagic server":`Save failed: ${n?.message||"Unknown error"}`;i&&(i.innerHTML=s,i.className="om-btn",i.disabled=!1),setTimeout(()=>{a.saveStatus="",y()},4e3)}}function H(){let e=h.querySelector('[data-action="save-settings"]');e&&(a.saveStatus==="saving"?(e.innerHTML='<span class="om-spinner"></span> Saving...',e.className="om-btn om-btn-saving",e.disabled=!0):a.saveStatus==="saved"?(e.innerHTML=`${c.check} Saved`,e.className="om-btn om-btn-saved",e.disabled=!1):a.saveStatus==="error"?(e.innerHTML="Save failed - try again",e.className="om-btn",e.disabled=!1):(e.innerHTML="Save",e.className="om-btn",e.disabled=!1))}async function le(){let e=x.value.trim();if(!e||a.streaming)return;if(!a.hasApiKey||!a.provider){v("settings");return}a.messages.push({role:"user",content:e}),a.streaming=!0,a.streamContent="",x.value="",v("chat");let t=Q(a.selectedElement,a.screenshot);t.pageUrl=window.location.href,t.pageTitle=document.title;try{let o=await B("llm.chat",{provider:a.provider,model:a.model,messages:a.messages.map(n=>({role:n.role,content:n.content})),context:t},n=>{a.streamContent+=n;let i=h.querySelector(".om-msg-assistant:last-child");i&&(i.innerHTML=`<span class="om-spinner"></span>${D(a.streamContent)}`,re())});if(a.messages.push({role:"assistant",content:a.streamContent||o?.content||""}),o?.modifications?.length){for(let n of o.modifications)if(n.type==="edit"&&n.file&&n.search&&n.replace)try{let s=(await w("fs.read",{path:ne(n.file)})).payload?.content;s?.includes(n.search)&&(await w("fs.write",{path:ne(n.file),content:s.replace(n.search,n.replace)}),a.messages.push({role:"system",content:`Applied change to ${n.file}`}))}catch(i){a.messages.push({role:"system",content:`Failed: ${n.file} - ${i.message}`})}}}catch(o){a.messages.push({role:"system",content:`Error: ${o.message}`})}a.streaming=!1,a.streamContent="",y()}function ne(e){return a.roots.length>0?a.roots[0]+"/"+e:e}var S=null,L=null;function Pe(){a.selecting?ce():Ne()}function Ne(){a.selecting=!0,document.body.style.cursor="crosshair",M(),L=e=>{let t=e.target;if(t.closest("openmagic-toolbar")||t.dataset?.openmagic)return;let o=t.getBoundingClientRect();G({x:o.x,y:o.y,width:o.width,height:o.height})},S=e=>{e.preventDefault(),e.stopPropagation();let t=e.target;t.closest("openmagic-toolbar")||t.dataset?.openmagic||(a.selectedElement=U(t),ce(),$(),x.focus())},document.addEventListener("mousemove",L,!0),document.addEventListener("click",S,!0)}function ce(){a.selecting=!1,document.body.style.cursor="",I(),L&&(document.removeEventListener("mousemove",L,!0),L=null),S&&(document.removeEventListener("click",S,!0),S=null),M()}async function _e(){let e=await j();e&&(a.screenshot=e,$(),x.focus())}function Oe(){let e=!1,t=0,o=0,n=0,i=0;u.addEventListener("mousedown",s=>{let r=s.target;if(r.closest("[data-action]")||!r.closest(".om-grab")&&!r.closest(".om-pill-brand"))return;e=!0,t=s.clientX,o=s.clientY;let l=u.getBoundingClientRect();n=l.left,i=l.top,s.preventDefault()}),document.addEventListener("mousemove",s=>{if(!e)return;u.style.left=n+s.clientX-t+"px",u.style.top=i+s.clientY-o+"px",u.style.right="auto",u.style.bottom="auto";let r=u.getBoundingClientRect();k.style.right="auto",k.style.bottom="auto",k.style.left=r.left+"px",k.style.top=r.top-42+"px",g.style.right="auto",g.style.bottom="auto",g.style.left=r.left+"px",g.style.top=r.top-42-(g.classList.contains("om-hidden")?0:g.offsetHeight+6)+"px"}),document.addEventListener("mouseup",()=>{e=!1})}function D(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}function Re(){fetch("https://registry.npmjs.org/openmagic/latest",{headers:{Accept:"application/json"},signal:AbortSignal.timeout(5e3)}).then(e=>e.ok?e.json():null).then(e=>{if(!e?.version)return;let t=e.version.split(".").map(Number),o=ae.split(".").map(Number);for(let n=0;n<3;n++){if((t[n]||0)>(o[n]||0)){a.updateAvailable=!0,a.latestVersion=e.version,De();return}if((t[n]||0)<(o[n]||0))return}}).catch(()=>{})}function De(){if(f.querySelector(".om-update-dot"))return;let t=document.createElement("span");t.className="om-update-dot",t.title=`v${a.latestVersion} available`,t.addEventListener("click",()=>v("settings")),u.appendChild(t)}typeof window<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",ee):ee());})();
312
+ </div>`}function Ce(){if(!a.hasApiKey||!a.provider)return'<div class="om-status om-status-error">Configure your provider in Settings first</div>';let e=a.messages.map(n=>`<div class="om-msg om-msg-${n.role}">${R(n.content)}</div>`).join(""),t=a.streaming?`<div class="om-msg om-msg-assistant"><span class="om-spinner"></span>${R(a.streamContent)}</div>`:"";return`<div class="om-chat-messages">${!a.messages.length&&!a.streaming?'<div class="om-chat-empty">Select an element or type below to start</div>':""}${e}${t}</div>`}function O(){requestAnimationFrame(()=>{let e=u.querySelector(".om-chat-messages");e&&(e.scrollTop=e.scrollHeight)})}async function He(){let t=u.querySelector('[data-field="apiKey"]')?.value||"";if(!a.provider){a.saveStatus="error",T(),setTimeout(()=>{a.saveStatus="",b()},2e3);return}if(!U()){a.saveStatus="error",T();let n=u.querySelector('[data-action="save-settings"]');n&&(n.innerHTML="Not connected - check terminal"),setTimeout(()=>{a.saveStatus="",b()},3e3);return}let o={provider:a.provider,model:a.model};t&&(o.apiKey=t),a.saveStatus="saving",T();try{let n=await Promise.race([v("config.set",o),new Promise((i,s)=>setTimeout(()=>s(new Error("Save timed out")),8e3))]);a.hasApiKey=!!(t||a.hasApiKey),a.saveStatus="saved",T(),setTimeout(()=>{a.saveStatus="",a.activePanel==="settings"&&x("chat")},1200)}catch(n){a.saveStatus="error";let i=u.querySelector('[data-action="save-settings"]'),s=(n?.message||"").includes("timeout")?"Connection timeout - is the CLI running?":(n?.message||"").includes("connected")?"Not connected to OpenMagic server":`Save failed: ${n?.message||"Unknown error"}`;i&&(i.innerHTML=s,i.className="om-btn",i.disabled=!1),setTimeout(()=>{a.saveStatus="",b()},4e3)}}function T(){let e=u.querySelector('[data-action="save-settings"]');e&&(a.saveStatus==="saving"?(e.innerHTML='<span class="om-spinner"></span> Saving...',e.className="om-btn om-btn-saving",e.disabled=!0):a.saveStatus==="saved"?(e.innerHTML=`${c.check} Saved`,e.className="om-btn om-btn-saved",e.disabled=!1):a.saveStatus==="error"?(e.innerHTML="Save failed - try again",e.className="om-btn",e.disabled=!1):(e.innerHTML="Save",e.className="om-btn",e.disabled=!1))}async function ie(){let e=y.value.trim();if(!e||a.streaming)return;if(!a.hasApiKey||!a.provider){x("settings");return}a.messages.push({role:"user",content:e}),a.streaming=!0,a.streamContent="",y.value="",x("chat");let t=Q(a.selectedElement,a.screenshot);t.pageUrl=window.location.href,t.pageTitle=document.title;try{let o=await B("llm.chat",{provider:a.provider,model:a.model,messages:a.messages.map(n=>({role:n.role,content:n.content})),context:t},n=>{a.streamContent+=n;let i=u.querySelector(".om-msg-assistant:last-child");i&&(i.innerHTML=`<span class="om-spinner"></span>${R(a.streamContent)}`,O())});if(a.messages.push({role:"assistant",content:a.streamContent||o?.content||""}),o?.modifications?.length){for(let n of o.modifications)if(n.type==="edit"&&n.file&&n.search&&n.replace)try{let s=(await v("fs.read",{path:ne(n.file)})).payload?.content;s?.includes(n.search)&&(await v("fs.write",{path:ne(n.file),content:s.replace(n.search,n.replace)}),a.messages.push({role:"system",content:`Applied change to ${n.file}`}))}catch(i){a.messages.push({role:"system",content:`Failed: ${n.file} - ${i.message}`})}}}catch(o){a.messages.push({role:"system",content:`Error: ${o.message}`})}a.streaming=!1,a.streamContent="",b(),O()}function ne(e){return a.roots.length>0?a.roots[0]+"/"+e:e}var w=null,k=null;function $e(){a.selecting?re():Pe()}function Pe(){a.selecting=!0,document.body.style.cursor="crosshair",S(),k=e=>{let t=e.target;if(t.closest("openmagic-toolbar")||t.dataset?.openmagic)return;let o=t.getBoundingClientRect();G({x:o.x,y:o.y,width:o.width,height:o.height})},w=e=>{e.preventDefault(),e.stopPropagation();let t=e.target;t.closest("openmagic-toolbar")||t.dataset?.openmagic||(a.selectedElement=z(t),re(),C(),y.focus())},document.addEventListener("mousemove",k,!0),document.addEventListener("click",w,!0)}function re(){a.selecting=!1,document.body.style.cursor="",I(),k&&(document.removeEventListener("mousemove",k,!0),k=null),w&&(document.removeEventListener("click",w,!0),w=null),S()}async function Ne(){let e=await K();e&&(a.screenshot=e,C(),y.focus())}function _e(){let e=!1,t=0,o=0,n=0,i=0;h.addEventListener("mousedown",s=>{let r=s.target;if(r.closest("[data-action]")||!r.closest(".om-grab")&&!r.closest(".om-pill-brand"))return;e=!0,t=s.clientX,o=s.clientY;let l=h.getBoundingClientRect();n=l.left,i=l.top,s.preventDefault()}),document.addEventListener("mousemove",s=>{e&&(h.style.left=n+s.clientX-t+"px",h.style.top=i+s.clientY-o+"px",h.style.right="auto",h.style.bottom="auto")}),document.addEventListener("mouseup",()=>{e=!1})}function R(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}function Oe(){fetch("https://registry.npmjs.org/openmagic/latest",{headers:{Accept:"application/json"},signal:AbortSignal.timeout(5e3)}).then(e=>e.ok?e.json():null).then(e=>{if(!e?.version)return;let t=e.version.split(".").map(Number),o=Se.split(".").map(Number);for(let n=0;n<3;n++){if((t[n]||0)>(o[n]||0)){a.updateAvailable=!0,a.latestVersion=e.version,Re();return}if((t[n]||0)<(o[n]||0))return}}).catch(()=>{})}function Re(){if(g.querySelector(".om-update-dot"))return;let t=document.createElement("span");t.className="om-update-dot",t.title=`v${a.latestVersion} available`,t.addEventListener("click",()=>x("settings"));let o=g.querySelector(".om-toolbar-header");o&&o.appendChild(t)}typeof window<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",ee):ee());})();
343
313
  //# sourceMappingURL=index.global.js.map