openmagic 0.6.0 → 0.8.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,4 +1,5 @@
1
- "use strict";var OpenMagicToolbar=(()=>{var $=`
1
+ #!/usr/bin/env node
2
+ "use strict";var OpenMagicToolbar=(()=>{var B=`
2
3
  :host {
3
4
  all: initial;
4
5
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
@@ -7,13 +8,11 @@
7
8
  line-height: 1.5;
8
9
  }
9
10
 
10
- * {
11
- box-sizing: border-box;
12
- margin: 0;
13
- padding: 0;
14
- }
11
+ * { box-sizing: border-box; margin: 0; padding: 0; }
12
+
13
+ .om-hidden { display: none !important; }
15
14
 
16
- /* Floating Pill */
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 */
17
16
  .om-pill {
18
17
  position: fixed;
19
18
  bottom: 24px;
@@ -22,753 +21,323 @@
22
21
  display: flex;
23
22
  align-items: center;
24
23
  gap: 2px;
25
- padding: 6px 12px 6px 6px;
26
- background: linear-gradient(135deg, #13132b 0%, #1a1a3e 100%);
27
- border: 1px solid rgba(108, 92, 231, 0.25);
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);
28
27
  border-radius: 12px;
29
28
  user-select: none;
30
- box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(108, 92, 231, 0.08);
31
- transition: box-shadow 0.2s, transform 0.15s;
32
- }
33
-
34
- .om-pill:hover {
35
- box-shadow: 0 6px 32px rgba(108, 92, 231, 0.25), 0 0 0 1px rgba(108, 92, 231, 0.3);
36
- transform: translateY(-1px);
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;
37
31
  }
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); }
38
33
 
39
- /* Six-dot grab handle */
40
34
  .om-grab {
41
- display: flex;
42
- align-items: center;
43
- justify-content: center;
44
- width: 20px;
45
- height: 28px;
46
- color: #444;
47
- cursor: grab;
48
- border-radius: 6px;
49
- transition: color 0.15s, background 0.15s;
50
- flex-shrink: 0;
35
+ display: flex; align-items: center; justify-content: center;
36
+ width: 18px; height: 26px; color: #3a3a5a; cursor: grab;
37
+ border-radius: 5px; transition: color 0.15s; flex-shrink: 0;
51
38
  }
39
+ .om-grab:hover { color: #6c5ce7; }
40
+ .om-grab:active { cursor: grabbing; color: #a29bfe; }
52
41
 
53
- .om-grab:hover {
54
- color: #888;
55
- background: rgba(255, 255, 255, 0.05);
56
- }
57
-
58
- .om-grab:active {
59
- cursor: grabbing;
60
- color: #a29bfe;
61
- }
62
-
63
- /* Brand */
64
42
  .om-pill-brand {
65
- display: flex;
66
- align-items: center;
67
- gap: 6px;
68
- padding: 0 6px;
69
- }
70
-
71
- .om-pill-icon {
72
- color: #a29bfe;
73
- flex-shrink: 0;
43
+ display: flex; align-items: center; gap: 5px;
44
+ padding: 0 6px 0 4px; cursor: grab;
74
45
  }
46
+ .om-pill-icon { color: #a29bfe; flex-shrink: 0; }
47
+ .om-pill-text { font-size: 11px; font-weight: 700; color: #a29bfe; letter-spacing: 0.3px; white-space: nowrap; }
75
48
 
76
- .om-pill-text {
77
- font-size: 12px;
78
- font-weight: 700;
79
- color: #c4b5fd;
80
- letter-spacing: 0.3px;
81
- white-space: nowrap;
82
- }
49
+ .om-pill-divider { width: 1px; height: 18px; background: rgba(255,255,255,0.07); margin: 0 3px; }
83
50
 
84
51
  .om-pill-btn {
85
- background: none;
86
- border: none;
87
- color: #888;
88
- cursor: pointer;
89
- padding: 6px;
90
- border-radius: 8px;
91
- line-height: 1;
52
+ background: none; border: none; color: #555; cursor: pointer;
53
+ padding: 5px 6px; border-radius: 6px; line-height: 1;
92
54
  transition: background 0.15s, color 0.15s;
93
- display: flex;
94
- align-items: center;
95
- justify-content: center;
96
- position: relative;
55
+ display: flex; align-items: center; justify-content: center;
97
56
  }
57
+ .om-pill-btn:hover { background: rgba(108, 92, 231, 0.15); color: #a29bfe; }
58
+ .om-pill-btn.active { background: rgba(108, 92, 231, 0.25); color: #c4b5fd; }
98
59
 
99
- .om-pill-btn:hover {
100
- background: rgba(108, 92, 231, 0.2);
60
+ .om-status-dot {
61
+ width: 7px; height: 7px; border-radius: 50%; margin-left: 4px; flex-shrink: 0;
101
62
  }
63
+ .om-status-dot.connected { background: #00b894; }
64
+ .om-status-dot.disconnected { background: #e94560; }
102
65
 
103
- .om-pill-btn.active {
104
- background: rgba(108, 92, 231, 0.3);
105
- color: #a29bfe;
66
+ .om-update-dot {
67
+ width: 7px; height: 7px; border-radius: 50%; background: #fdcb6e;
68
+ margin-left: 4px; cursor: pointer; flex-shrink: 0;
69
+ animation: om-pulse 2s ease infinite;
106
70
  }
107
-
108
- .om-pill-divider {
109
- width: 1px;
110
- height: 20px;
111
- background: rgba(255, 255, 255, 0.1);
112
- margin: 0 4px;
71
+ @keyframes om-pulse {
72
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(253,203,110,0.4); }
73
+ 50% { box-shadow: 0 0 0 5px rgba(253,203,110,0); }
113
74
  }
114
75
 
115
- /* Panel */
116
- .om-panel {
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 {
117
78
  position: fixed;
118
- bottom: 80px;
79
+ bottom: 62px;
119
80
  right: 24px;
120
81
  z-index: 2147483647;
121
- width: 420px;
122
- max-height: 600px;
123
- background: #1a1a2e;
124
- border: 1px solid rgba(108, 92, 231, 0.2);
125
- border-radius: 16px;
126
- box-shadow: 0 8px 48px rgba(0, 0, 0, 0.5);
127
- display: flex;
128
- flex-direction: column;
129
- overflow: hidden;
130
- animation: om-slide-up 0.2s ease;
131
- }
132
-
133
- @keyframes om-slide-up {
134
- from { opacity: 0; transform: translateY(8px); }
135
- to { opacity: 1; transform: translateY(0); }
136
- }
137
-
138
- .om-panel-header {
139
82
  display: flex;
140
83
  align-items: center;
141
- justify-content: space-between;
142
- padding: 12px 16px;
143
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
144
- background: rgba(108, 92, 231, 0.05);
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;
145
91
  }
146
-
147
- .om-panel-title {
148
- font-size: 13px;
149
- font-weight: 600;
150
- color: #a29bfe;
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);
151
95
  }
152
96
 
153
- .om-panel-close {
154
- background: none;
97
+ .om-prompt-input {
98
+ flex: 1;
99
+ background: transparent;
155
100
  border: none;
156
- color: #666;
157
- cursor: pointer;
158
- font-size: 18px;
159
- padding: 2px 6px;
160
- border-radius: 4px;
161
- line-height: 1;
162
- }
163
-
164
- .om-panel-close:hover {
165
101
  color: #e0e0e0;
166
- background: rgba(255, 255, 255, 0.05);
102
+ font-size: 13px;
103
+ font-family: inherit;
104
+ padding: 8px 12px;
105
+ outline: none;
106
+ min-width: 0;
167
107
  }
108
+ .om-prompt-input::placeholder { color: #444; }
168
109
 
169
- .om-panel-body {
170
- flex: 1;
171
- overflow-y: auto;
172
- padding: 16px;
110
+ .om-prompt-context {
111
+ display: flex; gap: 3px; padding: 0 4px; flex-shrink: 0;
173
112
  }
174
-
175
- .om-panel-body::-webkit-scrollbar {
176
- width: 6px;
113
+ .om-prompt-chip {
114
+ 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
+ border-radius: 6px; font-size: 10px; color: #a29bfe;
118
+ cursor: default; white-space: nowrap;
177
119
  }
178
-
179
- .om-panel-body::-webkit-scrollbar-track {
180
- background: transparent;
120
+ .om-prompt-chip-x {
121
+ background: none; border: none; color: #a29bfe; cursor: pointer;
122
+ font-size: 12px; line-height: 1; padding: 0 1px; opacity: 0.6;
181
123
  }
124
+ .om-prompt-chip-x:hover { opacity: 1; }
182
125
 
183
- .om-panel-body::-webkit-scrollbar-thumb {
184
- background: rgba(255, 255, 255, 0.1);
185
- border-radius: 3px;
126
+ .om-prompt-send {
127
+ display: flex; align-items: center; justify-content: center;
128
+ width: 32px; height: 32px; flex-shrink: 0;
129
+ background: #6c5ce7; border: none; border-radius: 8px;
130
+ color: white; cursor: pointer; transition: background 0.15s;
186
131
  }
132
+ .om-prompt-send:hover { background: #7c6cf7; }
133
+ .om-prompt-send:disabled { background: #2a2a4a; color: #555; cursor: not-allowed; }
187
134
 
188
- /* Chat */
189
- .om-chat-messages {
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);
190
147
  display: flex;
191
148
  flex-direction: column;
192
- gap: 12px;
193
- min-height: 200px;
194
- max-height: 380px;
195
- overflow-y: auto;
196
- padding-bottom: 8px;
197
- }
198
-
199
- .om-chat-messages::-webkit-scrollbar {
200
- width: 4px;
201
- }
202
-
203
- .om-chat-messages::-webkit-scrollbar-thumb {
204
- background: rgba(255, 255, 255, 0.1);
205
- border-radius: 2px;
206
- }
207
-
208
- .om-msg {
209
- padding: 10px 14px;
210
- border-radius: 12px;
211
- font-size: 13px;
212
- line-height: 1.5;
213
- white-space: pre-wrap;
214
- word-break: break-word;
215
- }
216
-
217
- .om-msg-user {
218
- background: rgba(108, 92, 231, 0.15);
219
- color: #e0e0e0;
220
- margin-left: 32px;
221
- border-bottom-right-radius: 4px;
222
- }
223
-
224
- .om-msg-assistant {
225
- background: rgba(255, 255, 255, 0.03);
226
- color: #ccc;
227
- margin-right: 32px;
228
- border-bottom-left-radius: 4px;
229
- border: 1px solid rgba(255, 255, 255, 0.05);
230
- }
231
-
232
- .om-msg-system {
233
- background: rgba(233, 69, 96, 0.1);
234
- color: #e94560;
235
- font-size: 12px;
236
- text-align: center;
237
- padding: 8px;
149
+ overflow: hidden;
150
+ animation: om-slide-up 0.15s ease;
238
151
  }
239
-
240
- .om-chat-input-wrap {
241
- display: flex;
242
- gap: 8px;
243
- margin-top: 12px;
152
+ @keyframes om-slide-up {
153
+ from { opacity: 0; transform: translateY(6px); }
154
+ to { opacity: 1; transform: translateY(0); }
244
155
  }
245
156
 
246
- .om-chat-input {
247
- flex: 1;
248
- background: rgba(255, 255, 255, 0.05);
249
- border: 1px solid rgba(255, 255, 255, 0.1);
250
- border-radius: 10px;
157
+ .om-panel-header {
158
+ display: flex; align-items: center; gap: 8px;
251
159
  padding: 10px 14px;
252
- color: #e0e0e0;
253
- font-size: 13px;
254
- font-family: inherit;
255
- outline: none;
256
- resize: none;
257
- min-height: 40px;
258
- max-height: 120px;
160
+ border-bottom: 1px solid rgba(255,255,255,0.04);
161
+ background: rgba(108, 92, 231, 0.03);
259
162
  }
260
-
261
- .om-chat-input:focus {
262
- border-color: rgba(108, 92, 231, 0.5);
263
- }
264
-
265
- .om-chat-input::placeholder {
266
- color: #555;
267
- }
268
-
269
- .om-chat-send {
270
- background: #6c5ce7;
271
- border: none;
272
- color: white;
273
- cursor: pointer;
274
- padding: 10px 16px;
275
- border-radius: 10px;
276
- font-size: 13px;
277
- font-weight: 600;
278
- transition: background 0.15s;
279
- white-space: nowrap;
280
- }
281
-
282
- .om-chat-send:hover {
283
- background: #7c6cf7;
284
- }
285
-
286
- .om-chat-send:disabled {
287
- background: #333;
288
- color: #666;
289
- cursor: not-allowed;
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;
290
169
  }
170
+ .om-panel-close:hover { color: #ccc; background: rgba(255,255,255,0.05); }
291
171
 
292
- /* Settings */
293
- .om-settings {
294
- display: flex;
295
- flex-direction: column;
296
- gap: 16px;
172
+ .om-panel-body {
173
+ flex: 1; overflow-y: auto; padding: 14px;
297
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; }
298
178
 
299
- .om-field {
300
- display: flex;
301
- flex-direction: column;
302
- gap: 6px;
303
- }
179
+ /* \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; }
304
181
 
305
- .om-label {
306
- font-size: 11px;
307
- font-weight: 600;
308
- text-transform: uppercase;
309
- letter-spacing: 0.5px;
310
- color: #888;
311
- }
182
+ .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; }
312
184
 
313
185
  .om-select, .om-input {
314
- background: rgba(255, 255, 255, 0.05);
315
- border: 1px solid rgba(255, 255, 255, 0.1);
186
+ background: rgba(255,255,255,0.04);
187
+ border: 1px solid rgba(255,255,255,0.08);
316
188
  border-radius: 8px;
317
- padding: 10px 12px;
189
+ padding: 9px 11px;
318
190
  color: #e0e0e0;
319
191
  font-size: 13px;
320
192
  font-family: inherit;
321
193
  outline: none;
322
194
  width: 100%;
195
+ transition: border-color 0.15s;
323
196
  }
197
+ .om-select:focus, .om-input:focus { border-color: rgba(108, 92, 231, 0.4); }
198
+ .om-select option { background: #151528; color: #e0e0e0; }
324
199
 
325
- .om-select:focus, .om-input:focus {
326
- border-color: rgba(108, 92, 231, 0.5);
327
- }
200
+ .om-key-row { display: flex; gap: 6px; align-items: stretch; }
201
+ .om-key-input { flex: 1; min-width: 0; }
328
202
 
329
- .om-select option {
330
- background: #1a1a2e;
331
- color: #e0e0e0;
203
+ .om-btn-get-key {
204
+ 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;
207
+ color: #a29bfe; font-size: 11px; font-weight: 600;
208
+ font-family: inherit; cursor: pointer; white-space: nowrap;
209
+ transition: all 0.15s;
332
210
  }
211
+ .om-btn-get-key:hover { background: rgba(108, 92, 231, 0.18); color: #c4b5fd; }
333
212
 
334
213
  .om-btn {
335
- background: #6c5ce7;
336
- border: none;
337
- color: white;
338
- cursor: pointer;
339
- padding: 10px 16px;
340
- border-radius: 8px;
341
- font-size: 13px;
342
- font-weight: 600;
214
+ display: flex; align-items: center; justify-content: center; gap: 6px;
215
+ background: #6c5ce7; border: none; color: white; cursor: pointer;
216
+ padding: 9px 16px; border-radius: 8px;
217
+ font-size: 13px; font-weight: 600; font-family: inherit;
343
218
  transition: background 0.15s;
344
219
  }
220
+ .om-btn:hover { background: #7c6cf7; }
221
+ .om-btn:disabled { background: #2a2a4a; color: #555; cursor: not-allowed; }
345
222
 
346
- .om-btn:hover {
347
- background: #7c6cf7;
348
- }
349
-
350
- .om-btn-secondary {
351
- background: rgba(255, 255, 255, 0.05);
352
- color: #e0e0e0;
353
- border: 1px solid rgba(255, 255, 255, 0.1);
354
- }
355
-
356
- .om-btn-secondary:hover {
357
- background: rgba(255, 255, 255, 0.1);
358
- }
359
-
360
- .om-status {
361
- font-size: 12px;
362
- padding: 6px 10px;
363
- border-radius: 6px;
364
- text-align: center;
365
- }
366
-
367
- .om-status-success {
368
- background: rgba(0, 184, 148, 0.1);
369
- color: #00b894;
370
- }
371
-
372
- .om-status-error {
373
- background: rgba(233, 69, 96, 0.1);
374
- color: #e94560;
375
- }
376
-
377
- /* Context bar */
378
- .om-context-bar {
379
- display: flex;
380
- gap: 6px;
381
- flex-wrap: wrap;
382
- margin-bottom: 8px;
383
- }
384
-
385
- .om-context-chip {
386
- display: flex;
387
- align-items: center;
388
- gap: 4px;
389
- padding: 4px 10px;
390
- background: rgba(108, 92, 231, 0.1);
391
- border: 1px solid rgba(108, 92, 231, 0.2);
392
- border-radius: 20px;
393
- font-size: 11px;
394
- color: #a29bfe;
395
- }
396
-
397
- .om-context-chip-remove {
398
- background: none;
399
- border: none;
400
- color: #a29bfe;
401
- cursor: pointer;
402
- font-size: 14px;
403
- padding: 0 2px;
404
- line-height: 1;
405
- }
223
+ .om-btn-saving { background: #4a3db0; }
224
+ .om-btn-saved { background: #00b894; }
406
225
 
407
- /* Diff */
408
- .om-diff {
409
- font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
410
- font-size: 12px;
411
- border-radius: 8px;
412
- overflow: hidden;
413
- border: 1px solid rgba(255, 255, 255, 0.05);
414
- margin: 8px 0;
415
- }
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; }
416
229
 
417
- .om-diff-header {
418
- padding: 8px 12px;
419
- background: rgba(255, 255, 255, 0.03);
420
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
421
- color: #888;
422
- font-size: 11px;
423
- }
230
+ .om-key-hint { font-size: 10px; color: #555; margin-top: 4px; line-height: 1.4; }
231
+ .om-key-hint a { color: #7c6cf7; cursor: pointer; text-decoration: none; }
232
+ .om-key-hint a:hover { text-decoration: underline; }
424
233
 
425
- .om-diff-line {
426
- padding: 2px 12px;
427
- white-space: pre;
428
- overflow-x: auto;
429
- }
430
-
431
- .om-diff-add {
432
- background: rgba(0, 184, 148, 0.1);
433
- color: #55efc4;
434
- }
435
-
436
- .om-diff-remove {
437
- background: rgba(233, 69, 96, 0.1);
438
- color: #fab1a0;
439
- }
440
-
441
- .om-diff-actions {
442
- display: flex;
443
- gap: 8px;
444
- padding: 8px 12px;
445
- border-top: 1px solid rgba(255, 255, 255, 0.05);
446
- background: rgba(255, 255, 255, 0.02);
447
- }
448
-
449
- /* Element info */
450
- .om-element-info {
451
- background: rgba(255, 255, 255, 0.03);
452
- border: 1px solid rgba(255, 255, 255, 0.05);
453
- border-radius: 8px;
454
- padding: 10px 12px;
455
- font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
456
- font-size: 11px;
457
- color: #888;
458
- margin: 8px 0;
459
- max-height: 100px;
460
- overflow-y: auto;
461
- }
462
-
463
- .om-hidden {
464
- display: none !important;
465
- }
466
-
467
- /* Loading */
468
- .om-loading {
469
- display: flex;
470
- align-items: center;
471
- gap: 8px;
472
- padding: 8px 12px;
473
- color: #888;
474
- font-size: 12px;
475
- }
476
-
477
- .om-spinner {
478
- width: 16px;
479
- height: 16px;
480
- border: 2px solid rgba(108, 92, 231, 0.2);
481
- border-top-color: #6c5ce7;
482
- border-radius: 50%;
483
- animation: om-spin 0.6s linear infinite;
484
- }
485
-
486
- @keyframes om-spin {
487
- to { transform: rotate(360deg); }
488
- }
489
-
490
- /* Tooltip */
491
- .om-tooltip {
492
- position: absolute;
493
- bottom: 100%;
494
- left: 50%;
495
- transform: translateX(-50%);
496
- background: #1a1a2e;
497
- color: #e0e0e0;
498
- padding: 4px 8px;
499
- border-radius: 4px;
500
- font-size: 11px;
501
- white-space: nowrap;
502
- pointer-events: none;
503
- opacity: 0;
504
- transition: opacity 0.15s;
505
- margin-bottom: 4px;
506
- }
507
-
508
- .om-pill-btn:hover .om-tooltip {
509
- opacity: 1;
510
- }
511
-
512
- /* Update indicator dot on pill */
513
- .om-update-dot {
514
- width: 10px;
515
- height: 10px;
516
- border-radius: 50%;
517
- background: #00b894;
518
- margin-left: 6px;
519
- cursor: pointer;
520
- position: relative;
521
- animation: om-pulse-green 2s ease infinite;
522
- flex-shrink: 0;
523
- }
524
-
525
- @keyframes om-pulse-green {
526
- 0%, 100% { box-shadow: 0 0 0 0 rgba(0, 184, 148, 0.5); }
527
- 50% { box-shadow: 0 0 0 6px rgba(0, 184, 148, 0); }
528
- }
529
-
530
- /* Update banner in settings */
531
234
  .om-update-banner {
532
- display: flex;
533
- align-items: center;
534
- gap: 8px;
535
- flex-wrap: wrap;
536
- padding: 10px 14px;
537
- margin-bottom: 16px;
538
- background: rgba(0, 184, 148, 0.08);
539
- border: 1px solid rgba(0, 184, 148, 0.2);
540
- border-radius: 10px;
541
- font-size: 13px;
542
- color: #00b894;
235
+ 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;
543
239
  }
544
-
545
- .om-update-current {
546
- font-size: 11px;
547
- color: #888;
548
- }
549
-
550
240
  .om-update-cmd {
551
- display: block;
552
- width: 100%;
553
- margin-top: 4px;
554
- padding: 6px 10px;
555
- background: rgba(0, 0, 0, 0.2);
556
- border-radius: 6px;
241
+ display: block; width: 100%; margin-top: 3px;
242
+ padding: 5px 8px; background: rgba(0, 0, 0, 0.15); border-radius: 5px;
557
243
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
558
- font-size: 12px;
559
- color: #55efc4;
560
- user-select: all;
561
- }
562
-
563
- /* Version in panel header */
564
- .om-panel-version {
565
- font-size: 11px;
566
- color: #555;
567
- margin-left: auto;
568
- margin-right: 8px;
569
- }
570
-
571
- .om-header-icon {
572
- color: #a29bfe;
573
- margin-right: 6px;
574
- flex-shrink: 0;
575
- }
576
-
577
- /* Auth tabs */
578
- .om-auth-tabs {
579
- display: flex;
580
- gap: 0;
581
- margin-bottom: 8px;
582
- border: 1px solid rgba(255, 255, 255, 0.1);
583
- border-radius: 8px;
584
- overflow: hidden;
585
- }
586
-
587
- .om-auth-tab {
588
- flex: 1;
589
- background: transparent;
590
- border: none;
591
- color: #888;
592
- padding: 8px 12px;
593
- font-size: 12px;
594
- font-weight: 600;
595
- font-family: inherit;
596
- cursor: pointer;
597
- transition: all 0.15s;
244
+ font-size: 11px; color: #fdcb6e; user-select: all;
598
245
  }
599
246
 
600
- .om-auth-tab:hover {
601
- color: #ccc;
602
- background: rgba(255, 255, 255, 0.03);
603
- }
604
-
605
- .om-auth-tab.active {
606
- background: rgba(108, 92, 231, 0.15);
607
- color: #a29bfe;
608
- }
609
-
610
- .om-auth-hint {
611
- background: rgba(255, 255, 255, 0.02);
612
- border: 1px solid rgba(255, 255, 255, 0.05);
613
- border-radius: 8px;
614
- padding: 10px 12px;
615
- margin-top: 8px;
616
- font-size: 12px;
617
- color: #888;
618
- line-height: 1.6;
619
- }
620
-
621
- .om-auth-hint p {
622
- margin-bottom: 6px;
247
+ /* \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
+ .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;
623
252
  }
253
+ .om-chat-messages::-webkit-scrollbar { width: 4px; }
254
+ .om-chat-messages::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 2px; }
624
255
 
625
- .om-auth-hint ol {
626
- padding-left: 18px;
256
+ .om-msg {
257
+ padding: 9px 12px; border-radius: 10px;
258
+ font-size: 13px; line-height: 1.55;
259
+ white-space: pre-wrap; word-break: break-word;
627
260
  }
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; }
628
264
 
629
- .om-auth-hint li {
630
- margin-bottom: 3px;
631
- }
265
+ .om-chat-empty { color: #3a3a5a; text-align: center; padding: 40px 20px; font-size: 13px; line-height: 1.6; }
632
266
 
633
- .om-auth-hint code {
634
- background: rgba(108, 92, 231, 0.1);
635
- padding: 1px 5px;
636
- border-radius: 3px;
637
- font-size: 11px;
638
- color: #a29bfe;
639
- }
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; }
268
+ @keyframes om-spin { to { transform: rotate(360deg); } }
640
269
 
641
- .om-auth-hint strong {
642
- color: #ccc;
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
+ .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;
274
+ font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
275
+ font-size: 10px; color: #666; max-height: 80px; overflow-y: auto; margin-bottom: 8px;
643
276
  }
644
- `;var u=null,p=new Map,Q=[],M=[],E=!1,k=null;function L(){return Math.random().toString(36).slice(2)+Date.now().toString(36)}function S(e,o){return new Promise((t,i)=>{try{u=new WebSocket(`ws://127.0.0.1:${e}/__openmagic__/ws`),u.onopen=()=>{let r=L();C({id:r,type:"handshake",payload:{token:o}}),p.set(r,a=>{if(a.type==="handshake.ok"){E=!0;for(let s of M)u?.send(s);M=[],t()}else a.type==="error"&&i(new Error(a.payload?.message||"Handshake failed"))})},u.onmessage=r=>{try{let a=JSON.parse(r.data);a.id&&p.has(a.id)&&(p.get(a.id)(a),(a.type==="llm.done"||a.type==="llm.error"||!a.type.startsWith("llm."))&&p.delete(a.id));for(let s of Q)s(a)}catch{}},u.onclose=()=>{E=!1,k||(k=setTimeout(()=>{k=null,S(e,o).catch(()=>{})},2e3))},u.onerror=()=>{}}catch(r){i(r)}})}function C(e){let o=JSON.stringify(e);u&&E?u.send(o):M.push(o)}function g(e,o){return new Promise((t,i)=>{let r=L(),a=setTimeout(()=>{p.delete(r),i(new Error("Request timeout"))},3e4);p.set(r,s=>{clearTimeout(a),s.type==="error"?i(new Error(s.payload?.message||"Unknown error")):t(s)}),C({id:r,type:e,payload:o})})}function N(e,o,t){return new Promise((i,r)=>{let a=L(),s=setTimeout(()=>{p.delete(a),r(new Error("Stream timeout"))},12e4);p.set(a,l=>{l.type==="llm.chunk"?t(l.payload?.delta||""):l.type==="llm.done"?(clearTimeout(s),p.delete(a),i(l.payload)):(l.type==="llm.error"||l.type==="error")&&(clearTimeout(s),p.delete(a),r(new Error(l.payload?.message||"Stream error")))}),C({id:a,type:e,payload:o})})}var Z=["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 O(e){let o=window.getComputedStyle(e),t={};for(let r of Z)t[r]=o.getPropertyValue(r);let i=e.getBoundingClientRect();return{tagName:e.tagName.toLowerCase(),id:e.id||"",className:e.className||"",textContent:(e.textContent||"").trim().slice(0,200),outerHTML:ee(e),cssSelector:te(e),xpath:oe(e),computedStyles:t,rect:{x:i.x,y:i.y,width:i.width,height:i.height}}}function ee(e){let o=e.cloneNode(!0);o.querySelectorAll("script, style, svg").forEach(r=>r.remove());let i=o.outerHTML;if(i.length>2e3){let r=e.tagName.toLowerCase(),a=Array.from(e.attributes).map(l=>`${l.name}="${l.value}"`).join(" "),s=Array.from(e.children).slice(0,5).map(l=>`<${l.tagName.toLowerCase()} .../>`).join(`
645
- `);i=`<${r} ${a}>
646
- ${s}
277
+ `;var g=null,p=new Map,ue=[],H=[],P=!1,$=null;function N(){return Math.random().toString(36).slice(2)+Date.now().toString(36)}function _(e,t){return new Promise((o,n)=>{try{g=new WebSocket(`ws://127.0.0.1:${e}/__openmagic__/ws`),g.onopen=()=>{let i=N();O({id:i,type:"handshake",payload:{token:t}}),p.set(i,s=>{if(s.type==="handshake.ok"){P=!0;for(let r of H)g?.send(r);H=[],o()}else s.type==="error"&&n(new Error(s.payload?.message||"Handshake failed"))})},g.onmessage=i=>{try{let s=JSON.parse(i.data);s.id&&p.has(s.id)&&(p.get(s.id)(s),(s.type==="llm.done"||s.type==="llm.error"||!s.type.startsWith("llm."))&&p.delete(s.id));for(let r of ue)r(s)}catch{}},g.onclose=()=>{P=!1,$||($=setTimeout(()=>{$=null,_(e,t).catch(()=>{})},2e3))},g.onerror=()=>{}}catch(i){n(i)}})}function O(e){let t=JSON.stringify(e);g&&P?g.send(t):H.push(t)}function v(e,t){return new Promise((o,n)=>{let i=N(),s=setTimeout(()=>{p.delete(i),n(new Error("Request timeout"))},3e4);p.set(i,r=>{clearTimeout(s),r.type==="error"?n(new Error(r.payload?.message||"Unknown error")):o(r)}),O({id:i,type:e,payload:t})})}function q(e,t,o){return new Promise((n,i)=>{let s=N(),r=setTimeout(()=>{p.delete(s),i(new Error("Stream timeout"))},12e4);p.set(s,l=>{l.type==="llm.chunk"?o(l.payload?.delta||""):l.type==="llm.done"?(clearTimeout(r),p.delete(s),n(l.payload)):(l.type==="llm.error"||l.type==="error")&&(clearTimeout(r),p.delete(s),i(new Error(l.payload?.message||"Stream error")))}),O({id:s,type:e,payload:t})})}var he=["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 he)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:fe(e),cssSelector:be(e),xpath:xe(e),computedStyles:o,rect:{x:n.x,y:n.y,width:n.width,height:n.height}}}function fe(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
+ `);n=`<${i} ${s}>
279
+ ${r}
647
280
  ${e.children.length>5?`<!-- +${e.children.length-5} more children -->`:""}
648
- </${r}>`}return i}function te(e){if(e.id)return`#${e.id}`;let o=[],t=e;for(;t&&t!==document.body;){let i=t.tagName.toLowerCase();if(t.id){o.unshift(`#${t.id}`);break}if(t.className&&typeof t.className=="string"){let a=t.className.trim().split(/\s+/).filter(s=>!s.startsWith("__")&&s.length<30).slice(0,2);a.length>0&&(i+="."+a.join("."))}let r=t.parentElement;if(r){let a=Array.from(r.children).filter(s=>s.tagName===t.tagName);if(a.length>1){let s=a.indexOf(t)+1;i+=`:nth-child(${s})`}}o.unshift(i),t=t.parentElement}return o.join(" > ")}function oe(e){let o=[],t=e;for(;t&&t!==document;){if(t.nodeType===Node.ELEMENT_NODE){let i=t,r=1,a=i.previousElementSibling;for(;a;)a.tagName===i.tagName&&r++,a=a.previousElementSibling;o.unshift(`${i.tagName.toLowerCase()}[${r}]`)}t=t.parentNode}return"/"+o.join("/")}var d=null;function A(e){d||(d=document.createElement("div"),d.style.cssText=`
281
+ </${i}>`}return n}function be(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 U(e){d||(d=document.createElement("div"),d.style.cssText=`
649
282
  position: fixed;
650
283
  pointer-events: none;
651
284
  z-index: 2147483646;
652
285
  border: 2px solid #6c5ce7;
653
286
  background: rgba(108, 92, 231, 0.1);
654
287
  transition: all 0.1s ease;
655
- `,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 _(){d&&(d.style.display="none")}async function R(e){try{return e?await ae(e):await ne()}catch(o){return console.warn("[OpenMagic] Screenshot capture failed:",o),null}}async function ne(){let e=document.createElement("canvas"),o=window.devicePixelRatio||1;e.width=window.innerWidth*o,e.height=window.innerHeight*o;let t=e.getContext("2d");t.scale(o,o);try{let i=await q(document.body),r=await D(i,window.innerWidth,window.innerHeight);return t.drawImage(r,0,0),e.toDataURL("image/png")}catch{return null}}async function ae(e){let o=e.getBoundingClientRect(),t=document.createElement("canvas"),i=window.devicePixelRatio||1;t.width=o.width*i,t.height=o.height*i;let r=t.getContext("2d");r.scale(i,i);try{let a=await q(e),s=await D(a,o.width,o.height);return r.drawImage(s,0,0),t.toDataURL("image/png")}catch{return null}}function q(e){return new Promise(o=>{let t=e.cloneNode(!0);z(e,t);let i=e.getBoundingClientRect(),r=i.width,a=i.height,s=`
656
- <svg xmlns="http://www.w3.org/2000/svg" width="${r}" height="${a}">
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 G(){d&&(d.style.display="none")}async function I(e){try{return e?await ve(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 V(n,window.innerWidth,window.innerHeight);return o.drawImage(i,0,0),e.toDataURL("image/png")}catch{return null}}async function ve(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 V(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);K(e,o);let n=e.getBoundingClientRect(),i=n.width,s=n.height,r=`
289
+ <svg xmlns="http://www.w3.org/2000/svg" width="${i}" height="${s}">
657
290
  <foreignObject width="100%" height="100%">
658
- <div xmlns="http://www.w3.org/1999/xhtml" style="width:${r}px;height:${a}px;overflow:hidden;">
659
- ${t.outerHTML}
291
+ <div xmlns="http://www.w3.org/1999/xhtml" style="width:${i}px;height:${s}px;overflow:hidden;">
292
+ ${o.outerHTML}
660
293
  </div>
661
294
  </foreignObject>
662
- </svg>`;o(s)})}function z(e,o){let t=window.getComputedStyle(e),i="";for(let s=0;s<t.length;s++){let l=t[s];i+=`${l}:${t.getPropertyValue(l)};`}o.style.cssText=i;let r=e.children,a=o.children;for(let s=0;s<r.length&&s<a.length;s++)z(r[s],a[s])}function D(e,o,t){return new Promise((i,r)=>{let a=new Image,s=new Blob([e],{type:"image/svg+xml;charset=utf-8"}),l=URL.createObjectURL(s);a.onload=()=>{URL.revokeObjectURL(l),i(a)},a.onerror=()=>{URL.revokeObjectURL(l),r(new Error("Failed to load SVG image"))},a.width=o,a.height=t,a.src=l})}var x=[];var G=!1;function I(){if(G)return;G=!0;let e=window.fetch;window.fetch=async function(...i){let r=new Request(...i),a={method:r.method,url:r.url,timestamp:Date.now()};try{let s=await e.apply(this,i);return a.status=s.status,a.duration=Date.now()-a.timestamp,T(a),s}catch(s){throw a.status=0,a.duration=Date.now()-a.timestamp,T(a),s}};let o=XMLHttpRequest.prototype.open,t=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.open=function(i,r,...a){return this.__om_method=i,this.__om_url=r,this.__om_start=Date.now(),o.apply(this,[i,r,...a])},XMLHttpRequest.prototype.send=function(...i){return this.addEventListener("loadend",()=>{T({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()})}),t.apply(this,i)}}function T(e){e.url.includes("__openmagic__")||(x.push(e),x.length>50&&x.shift())}function ie(){return[...x]}var v=[],re=100,j=!1;function K(){if(j)return;j=!0;let e=["log","warn","error","info","debug"];for(let o of e){let t=console[o];console[o]=function(...i){v.push({level:o,args:i.map(r=>{try{return typeof r=="object"?JSON.stringify(r).slice(0,500):String(r)}catch{return String(r)}}),timestamp:Date.now()}),v.length>re&&v.shift(),t.apply(console,i)}}}function se(){return[...v]}function B(e,o){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:o||void 0,networkLogs:ie().map(t=>({method:t.method,url:t.url,status:t.status,duration:t.duration,timestamp:t.timestamp})),consoleLogs:se().map(t=>({level:t.level,args:t.args,timestamp:t.timestamp}))}}var w={openai:{name:"OpenAI",models:[{id:"gpt-5.4",name:"GPT-5.4"},{id:"gpt-5.4-pro",name:"GPT-5.4 Pro"},{id:"gpt-5.4-mini",name:"GPT-5.4 Mini"},{id:"gpt-5.4-nano",name:"GPT-5.4 Nano"},{id:"gpt-5.2",name:"GPT-5.2 Thinking"},{id:"gpt-5.2-pro",name:"GPT-5.2 Pro"},{id:"o3",name:"o3 (Reasoning)"},{id:"o4-mini",name:"o4-mini (Reasoning)"},{id:"gpt-4.1",name:"GPT-4.1"},{id:"gpt-4.1-mini",name:"GPT-4.1 Mini"},{id:"codex-mini-latest",name:"Codex Mini"}],keyPlaceholder:"sk-..."},anthropic:{name:"Anthropic",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"},{id:"claude-sonnet-4-5-20250929",name:"Claude Sonnet 4.5"},{id:"claude-opus-4-5-20251101",name:"Claude Opus 4.5"},{id:"claude-sonnet-4-20250514",name:"Claude Sonnet 4"},{id:"claude-opus-4-20250514",name:"Claude Opus 4"}],keyPlaceholder:"sk-ant-..."},google:{name:"Google Gemini",models:[{id:"gemini-3.1-pro-preview",name:"Gemini 3.1 Pro"},{id:"gemini-3-flash-preview",name:"Gemini 3 Flash"},{id:"gemini-3.1-flash-lite-preview",name:"Gemini 3.1 Flash Lite"},{id:"gemini-2.5-pro",name:"Gemini 2.5 Pro"},{id:"gemini-2.5-flash",name:"Gemini 2.5 Flash"},{id:"gemini-2.5-flash-lite",name:"Gemini 2.5 Flash Lite"}],keyPlaceholder:"AIza..."},xai:{name:"xAI (Grok)",models:[{id:"grok-4.20-0309-reasoning",name:"Grok 4.20 Reasoning"},{id:"grok-4.20-0309-non-reasoning",name:"Grok 4.20"},{id:"grok-4-1-fast-reasoning",name:"Grok 4.1 Fast Reasoning"},{id:"grok-4-1-fast-non-reasoning",name:"Grok 4.1 Fast"}],keyPlaceholder:"xai-..."},deepseek:{name:"DeepSeek",models:[{id:"deepseek-chat",name:"DeepSeek V3.2"},{id:"deepseek-reasoner",name:"DeepSeek R1"}],keyPlaceholder:"sk-..."},mistral:{name:"Mistral",models:[{id:"mistral-large-3-25-12",name:"Mistral Large 3"},{id:"mistral-small-4-0-26-03",name:"Mistral Small 4"},{id:"codestral-2508",name:"Codestral"},{id:"devstral-2-25-12",name:"Devstral 2"},{id:"magistral-medium-1-2-25-09",name:"Magistral Medium"}],keyPlaceholder:"..."},groq:{name:"Groq",models:[{id:"meta-llama/llama-4-scout-17b-16e-instruct",name:"Llama 4 Scout 17B"},{id:"llama-3.3-70b-versatile",name:"Llama 3.3 70B"},{id:"llama-3.1-8b-instant",name:"Llama 3.1 8B Instant"},{id:"qwen/qwen3-32b",name:"Qwen 3 32B"}],keyPlaceholder:"gsk_..."},minimax:{name:"MiniMax",models:[{id:"MiniMax-M2.7",name:"MiniMax M2.7"},{id:"MiniMax-M2.7-highspeed",name:"M2.7 Highspeed"},{id:"MiniMax-M2.5",name:"MiniMax M2.5"}],keyPlaceholder:"MiniMax key..."},moonshot:{name:"Kimi (Moonshot)",models:[{id:"kimi-k2.5",name:"Kimi K2.5"},{id:"kimi-k2-thinking",name:"Kimi K2 Thinking"}],keyPlaceholder:"Moonshot key..."},qwen:{name:"Qwen (Alibaba)",models:[{id:"qwen3.5-plus",name:"Qwen 3.5 Plus"},{id:"qwen-max",name:"Qwen Max"},{id:"qwen-turbo",name:"Qwen Turbo"}],keyPlaceholder:"DashScope key..."},zhipu:{name:"Zhipu AI (GLM)",models:[{id:"glm-5",name:"GLM-5"},{id:"glm-4.7",name:"GLM-4.7"},{id:"glm-4.6",name:"GLM-4.6"}],keyPlaceholder:"Zhipu key..."},doubao:{name:"Doubao (ByteDance)",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"}],keyPlaceholder:"Volcano key..."},ollama:{name:"Ollama (Local)",models:[],keyPlaceholder:"not required",local:!0},openrouter:{name:"OpenRouter",models:[],keyPlaceholder:"sk-or-..."}},P="0.6.0",n={connected:!1,panelOpen:!1,activePanel:null,selecting:!1,selectedElement:null,screenshot:null,messages:[],streaming:!1,streamContent:"",provider:"",model:"",hasApiKey:!1,roots:[],updateAvailable:!1,latestVersion:""},y,h;function F(){if(document.querySelector("openmagic-toolbar"))return;let e=document.createElement("openmagic-toolbar");e.dataset.openmagic="true",y=e.attachShadow({mode:"closed"});let o=document.createElement("style");o.textContent=$,y.appendChild(o),h=document.createElement("div"),y.appendChild(h),document.body.appendChild(e),I(),K(),he();let t=window.__OPENMAGIC_CONFIG__;t&&S(t.wsPort,t.token).then(()=>{n.connected=!0,g("config.get").then(i=>{n.provider=i.payload?.provider||"",n.model=i.payload?.model||"",n.hasApiKey=i.payload?.hasApiKey||!1,n.roots=i.payload?.roots||[],(!n.provider||!n.hasApiKey)&&(n.panelOpen=!0,n.activePanel="settings"),c()})}).catch(i=>{console.error("[OpenMagic] Connection failed:",i),n.connected=!1,c()}),c()}function c(){if(h.innerHTML="",n.panelOpen&&n.activePanel){let o=document.createElement("div");o.className="om-panel",n.activePanel==="settings"?o.innerHTML=le():n.activePanel==="chat"&&(o.innerHTML=ce()),h.appendChild(o),de(o)}let e=document.createElement("div");if(e.className="om-pill",e.innerHTML=`
663
- <span class="om-grab" title="Drag to move">
664
- <svg width="8" 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>
665
- </span>
666
- <span class="om-pill-brand">
667
- <svg class="om-pill-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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>
668
- <span class="om-pill-text">OpenMagic</span>
669
- </span>
670
- <span class="om-pill-divider"></span>
671
- <button class="om-pill-btn ${n.selecting?"active":""}" data-action="select" title="Select Element">
672
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 7h10v10"/><path d="M7 17 17 7"/></svg>
673
- </button>
674
- <button class="om-pill-btn" data-action="screenshot" title="Screenshot">
675
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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>
676
- </button>
677
- <button class="om-pill-btn ${n.activePanel==="chat"?"active":""}" data-action="chat" title="Chat with AI">
678
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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>
679
- </button>
680
- <button class="om-pill-btn ${n.activePanel==="settings"?"active":""}" data-action="settings" title="Settings">
681
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
682
- </button>
683
- `,!n.connected){let o=document.createElement("span");o.style.cssText="width:8px;height:8px;border-radius:50%;background:#e94560;margin-left:4px;",e.appendChild(o)}if(n.updateAvailable){let o=document.createElement("span");o.className="om-update-dot",o.title=`Update available: v${n.latestVersion}`,o.addEventListener("click",t=>{t.stopPropagation(),n.panelOpen=!0,n.activePanel="settings",c()}),e.appendChild(o)}h.appendChild(e),ge(e),e.querySelectorAll(".om-pill-btn").forEach(o=>{o.addEventListener("click",t=>{t.stopPropagation();let i=o.dataset.action;i==="select"?pe():i==="screenshot"?ue():i==="chat"?X("chat"):i==="settings"&&X("settings")})})}function le(){let e=Object.entries(w).map(([l,m])=>`<option value="${l}" ${n.provider===l?"selected":""}>${m.name}</option>`).join(""),o=w[n.provider],t=o?o.models.map(l=>`<option value="${l.id}" ${n.model===l.id?"selected":""}>${l.name}</option>`).join(""):'<option value="">Select a provider first</option>',i=o?.keyPlaceholder||"Enter API key...",r=o?.local||!1,a=n.updateAvailable?`<div class="om-update-banner">
684
- <span>\u{1F680} v${n.latestVersion} available</span>
685
- <span class="om-update-current">current: v${P}</span>
686
- <code class="om-update-cmd">npx openmagic@latest</code>
687
- </div>`:"",s=n.provider==="openai"||n.provider==="anthropic";return`
688
- <div class="om-panel-header">
689
- <svg class="om-header-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
690
- <span class="om-panel-title">Settings</span>
691
- <span class="om-panel-version">v${P}</span>
692
- <button class="om-panel-close" data-action="close">&times;</button>
693
- </div>
694
- <div class="om-panel-body">
695
- ${a}
696
- <div class="om-settings">
697
- <div class="om-field">
698
- <label class="om-label">Provider</label>
699
- <select class="om-select" data-field="provider">
700
- <option value="">Select Provider...</option>
701
- ${e}
702
- </select>
703
- </div>
704
-
705
- <div class="om-field">
706
- <label class="om-label">Model</label>
707
- <select class="om-select" data-field="model">
708
- <option value="">Select Model...</option>
709
- ${t}
710
- </select>
711
- </div>
712
-
713
- <div class="om-field ${r?"om-hidden":""}">
714
- <label class="om-label">Authentication</label>
715
- ${s?`
716
- <div class="om-auth-tabs">
717
- <button class="om-auth-tab active" data-auth="apikey">API Key</button>
718
- <button class="om-auth-tab" data-auth="session">Session Token</button>
719
- </div>
720
- `:""}
721
- <input type="password" class="om-input" data-field="apiKey"
722
- placeholder="${i}"
723
- value="" />
724
- ${s?`
725
- <div class="om-auth-hint om-hidden" data-hint="session">
726
- <p>To use your existing account session:</p>
727
- <ol>
728
- <li>Go to <strong>${n.provider==="openai"?"platform.openai.com":"console.anthropic.com"}</strong></li>
729
- <li>Open DevTools \u2192 Application \u2192 Cookies</li>
730
- <li>Copy the <code>sessionKey</code> value</li>
731
- <li>Paste it above</li>
732
- </ol>
733
- </div>
734
- `:""}
735
- </div>
736
-
737
- <button class="om-btn" data-action="save-settings">Save Configuration</button>
738
-
739
- ${n.hasApiKey?'<div class="om-status om-status-success">Authenticated</div>':""}
740
- </div>
741
- </div>
742
- `}function ce(){if(!n.hasApiKey||!n.provider)return`
295
+ </svg>`;t(r)})}function K(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++)K(i[r],s[r])}function V(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 F=!1;function W(){if(F)return;F=!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__")||(M.push(e),M.length>50&&M.shift())}function we(){return[...M]}var E=[],ke=100,X=!1;function Y(){if(X)return;X=!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>ke&&E.shift(),o.apply(console,n)}}}function Se(){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:we().map(o=>({method:o.method,url:o.url,status:o.status,duration:o.duration,timestamp:o.timestamp})),consoleLogs:Se().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>'},J={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:[]}},ne="0.8.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:""},h,m,w,x,ae,u,f;function Z(){if(document.querySelector("openmagic-toolbar"))return;let e=document.createElement("openmagic-toolbar");e.dataset.openmagic="true",h=e.attachShadow({mode:"closed"});let t=document.createElement("style");t.textContent=B,h.appendChild(t);let o=document.createElement("div");h.appendChild(o),o.innerHTML=Le(),m=o.querySelector(".om-pill"),w=o.querySelector(".om-prompt-bar"),x=o.querySelector(".om-prompt-input"),ae=o.querySelector(".om-prompt-context"),u=o.querySelector(".om-panel"),f=o.querySelector(".om-panel-body"),document.body.appendChild(e),Me(o),_e(),W(),Y(),Oe();let n=window.__OPENMAGIC_CONFIG__;n&&_(n.wsPort,n.token).then(()=>(a.connected=!0,ee(),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)&&y("settings"),L()}).catch(()=>{a.connected=!1,ee()})}function Le(){return`
296
+ <div class="om-panel om-hidden">
743
297
  <div class="om-panel-header">
744
- <span class="om-panel-title">Chat</span>
745
- <button class="om-panel-close" data-action="close">&times;</button>
746
- </div>
747
- <div class="om-panel-body">
748
- <div class="om-status om-status-error">
749
- Configure your LLM provider in Settings first
750
- </div>
298
+ <span class="om-panel-title"></span>
299
+ <span class="om-panel-version">v${ne}</span>
300
+ <button class="om-panel-close" data-action="close-panel">${c.x}</button>
751
301
  </div>
752
- `;let e=n.messages.map(i=>`<div class="om-msg om-msg-${i.role}">${H(i.content)}</div>`).join(""),o=n.streaming?`<div class="om-msg om-msg-assistant"><div class="om-loading"><div class="om-spinner"></div> Thinking...</div>${H(n.streamContent)}</div>`:"",t=[];return n.selectedElement&&t.push(`<span class="om-context-chip">\u{1F3AF} ${n.selectedElement.tagName}${n.selectedElement.id?"#"+n.selectedElement.id:""} <button class="om-context-chip-remove" data-action="clear-element">&times;</button></span>`),n.screenshot&&t.push('<span class="om-context-chip">\u{1F4F8} Screenshot <button class="om-context-chip-remove" data-action="clear-screenshot">&times;</button></span>'),`
753
- <div class="om-panel-header">
754
- <span class="om-panel-title">Chat \u2014 ${w[n.provider]?.name||n.provider} / ${n.model}</span>
755
- <button class="om-panel-close" data-action="close">&times;</button>
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>
756
308
  </div>
757
- <div class="om-panel-body">
758
- ${t.length>0?`<div class="om-context-bar">${t.join("")}</div>`:""}
759
- ${n.selectedElement?`<div class="om-element-info">&lt;${n.selectedElement.tagName}${n.selectedElement.id?' id="'+n.selectedElement.id+'"':""}${n.selectedElement.className?' class="'+n.selectedElement.className.toString().slice(0,60)+'"':""}&gt;</div>`:""}
760
- <div class="om-chat-messages">
761
- ${e||'<div style="color:#555;text-align:center;padding:40px 0;font-size:13px;">Select an element or describe what you want to change</div>'}
762
- ${o}
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 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="",C()):n==="model"&&(a.model=o.value))}),x.addEventListener("keydown",t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),re())})}function Ee(e,t){switch(e){case"select":He();break;case"screenshot":Ne();break;case"chat":te("chat");break;case"settings":te("settings");break;case"close-panel":se();break;case"prompt-send":re();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,T();break;case"clear-screenshot":a.screenshot=null,T();break}}function ee(){let e=h.querySelector(".om-status-dot");e&&(e.className=`om-status-dot ${a.connected?"connected":"disconnected"}`)}function L(){h.querySelectorAll(".om-pill-btn").forEach(e=>{let t=e.dataset.action;e.classList.toggle("active",t===a.activePanel||t==="select"&&a.selecting)})}function T(){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 y(e){a.panelOpen=!0,a.activePanel=e,u.classList.remove("om-hidden");let t=h.querySelector(".om-panel-title");t.textContent=e==="settings"?"Settings":"Chat",C(),L()}function se(){a.panelOpen=!1,a.activePanel="",u.classList.add("om-hidden"),L()}function te(e){a.panelOpen&&a.activePanel===e?se():y(e)}function C(){a.activePanel==="settings"?f.innerHTML=Te():a.activePanel==="chat"&&(f.innerHTML=Ce(),ie())}function Te(){let e=Object.entries(J).map(([b,me])=>`<option value="${b}" ${a.provider===b?"selected":""}>${me.name}</option>`).join(""),t=J[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>`:"",ce=a.saveStatus==="saving"?'<span class="om-spinner"></span> Saving...':a.saveStatus==="saved"?`${c.check} Saved`:"Save",de=a.saveStatus==="saving"?"om-btn om-btn-saving":a.saveStatus==="saved"?"om-btn om-btn-saved":"om-btn",pe=a.saveStatus==="saving"?"disabled":"";return`
322
+ ${r}
323
+ <div class="om-settings">
324
+ <div class="om-field">
325
+ <label class="om-label">Provider</label>
326
+ <select class="om-select" data-field="provider"><option value="">Select Provider...</option>${e}</select>
763
327
  </div>
764
- <div class="om-chat-input-wrap">
765
- <textarea class="om-chat-input" placeholder="Describe the change you want..."
766
- rows="1" ${n.streaming?"disabled":""}></textarea>
767
- <button class="om-chat-send" data-action="send" ${n.streaming?"disabled":""}>
768
- ${n.streaming?"...":"Send"}
769
- </button>
328
+ <div class="om-field">
329
+ <label class="om-label">Model</label>
330
+ <select class="om-select" data-field="model"><option value="">Select Model...</option>${o}</select>
770
331
  </div>
771
- </div>
772
- `}function de(e){e.querySelector('[data-action="close"]')?.addEventListener("click",()=>{n.panelOpen=!1,n.activePanel=null,c()}),e.querySelector('[data-field="provider"]')?.addEventListener("change",t=>{n.provider=t.target.value,n.model="",c()}),e.querySelector('[data-field="model"]')?.addEventListener("change",t=>{n.model=t.target.value}),e.querySelectorAll(".om-auth-tab").forEach(t=>{t.addEventListener("click",()=>{e.querySelectorAll(".om-auth-tab").forEach(s=>s.classList.remove("active")),t.classList.add("active");let i=t.dataset.auth,r=e.querySelector('[data-hint="session"]'),a=e.querySelector('[data-field="apiKey"]');if(i==="session")r?.classList.remove("om-hidden"),a&&(a.placeholder="Paste session token...");else{r?.classList.add("om-hidden");let s=w[n.provider];a&&(a.placeholder=s?.keyPlaceholder||"Enter API key...")}})}),e.querySelector('[data-action="save-settings"]')?.addEventListener("click",()=>{let i=e.querySelector('[data-field="apiKey"]')?.value||"",r={provider:n.provider,model:n.model};i&&(r.apiKey=i),g("config.set",r).then(()=>{n.hasApiKey=!0,c()}).catch(a=>{console.error("[OpenMagic] Failed to save config:",a)})}),e.querySelector('[data-action="send"]')?.addEventListener("click",()=>{V(e)});let o=e.querySelector(".om-chat-input");o?.addEventListener("keydown",t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),V(e))}),o?.addEventListener("input",()=>{o.style.height="auto",o.style.height=Math.min(o.scrollHeight,120)+"px"}),e.querySelector('[data-action="clear-element"]')?.addEventListener("click",()=>{n.selectedElement=null,c()}),e.querySelector('[data-action="clear-screenshot"]')?.addEventListener("click",()=>{n.screenshot=null,c()})}async function V(e){let o=e.querySelector(".om-chat-input");if(!o)return;let t=o.value.trim();if(!t||n.streaming)return;n.messages.push({role:"user",content:t}),n.streaming=!0,n.streamContent="",c();let i=B(n.selectedElement,n.screenshot);try{let r=await N("llm.chat",{provider:n.provider,model:n.model,messages:n.messages.map(a=>({role:a.role,content:a.content})),context:i},a=>{n.streamContent+=a;let l=y.querySelector(".om-chat-messages")?.querySelector(".om-msg-assistant:last-child");l&&(l.innerHTML=H(n.streamContent))});if(n.messages.push({role:"assistant",content:n.streamContent||r?.content||""}),r?.modifications&&r.modifications.length>0){for(let a of r.modifications)if(a.type==="edit"&&a.file&&a.search&&a.replace)try{let l=(await g("fs.read",{path:U(a.file)})).payload?.content;if(l&&l.includes(a.search)){let m=l.replace(a.search,a.replace);await g("fs.write",{path:U(a.file),content:m}),n.messages.push({role:"system",content:`Applied change to ${a.file}`})}}catch(s){n.messages.push({role:"system",content:`Failed to apply change to ${a.file}: ${s.message}`})}}}catch(r){n.messages.push({role:"system",content:`Error: ${r.message}`})}n.streaming=!1,n.streamContent="",c()}function U(e){return n.roots.length>0?n.roots[0]+"/"+e:e}var f=null,b=null;function pe(){n.selecting?W():me()}function me(){n.selecting=!0,document.body.style.cursor="crosshair",b=e=>{let o=e.target;if(Y(o))return;let t=o.getBoundingClientRect();A({x:t.x,y:t.y,width:t.width,height:t.height})},f=e=>{e.preventDefault(),e.stopPropagation();let o=e.target;Y(o)||(n.selectedElement=O(o),W(),n.activePanel!=="chat"&&(n.panelOpen=!0,n.activePanel="chat"),c())},document.addEventListener("mousemove",b,!0),document.addEventListener("click",f,!0),c()}function W(){n.selecting=!1,document.body.style.cursor="",_(),b&&(document.removeEventListener("mousemove",b,!0),b=null),f&&(document.removeEventListener("click",f,!0),f=null),c()}async function ue(){let e=await R();e&&(n.screenshot=e,n.panelOpen=!0,n.activePanel="chat",c())}function X(e){n.panelOpen&&n.activePanel===e?(n.panelOpen=!1,n.activePanel=null):(n.panelOpen=!0,n.activePanel=e),c()}function ge(e){let o=!1,t=0,i=0,r=0,a=0;e.addEventListener("mousedown",s=>{let l=s.target;if(l.closest(".om-pill-btn")||!l.closest(".om-grab")&&!l.closest(".om-pill-brand"))return;o=!0,t=s.clientX,i=s.clientY;let m=e.getBoundingClientRect();r=m.left,a=m.top,s.preventDefault()}),document.addEventListener("mousemove",s=>{if(!o)return;let l=s.clientX-t,m=s.clientY-i;e.style.position="fixed",e.style.left=r+l+"px",e.style.top=a+m+"px",e.style.right="auto",e.style.bottom="auto"}),document.addEventListener("mouseup",()=>{o=!1})}function Y(e){return!!e.closest("openmagic-toolbar")||!!e.dataset?.openmagic}function H(e){let o=document.createElement("div");return o.textContent=e,o.innerHTML}function he(){fetch("https://registry.npmjs.org/openmagic/latest",{headers:{Accept:"application/json"},signal:AbortSignal.timeout(5e3)}).then(e=>{if(e.ok)return e.json()}).then(e=>{if(!e?.version)return;let o=e.version;fe(o,P)&&(n.updateAvailable=!0,n.latestVersion=o,c())}).catch(()=>{})}function fe(e,o){let t=e.split(".").map(Number),i=o.split(".").map(Number);for(let r=0;r<3;r++){if((t[r]||0)>(i[r]||0))return!0;if((t[r]||0)<(i[r]||0))return!1}return!1}typeof window<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",F):F());})();
773
- aded",F):F());})();
332
+ <div class="om-field ${n?"om-hidden":""}">
333
+ <label class="om-label">API Key</label>
334
+ <div class="om-key-row">
335
+ <input type="password" class="om-input om-key-input" data-field="apiKey" placeholder="${s}" />
336
+ ${i?`<button class="om-btn-get-key" data-action="get-key" data-url="${i}">${c.externalLink} Get key</button>`:""}
337
+ </div>
338
+ ${i?`<div class="om-key-hint"><a data-action="get-key" data-url="${i}">Get your ${t?.name||""} API key here</a></div>`:""}
339
+ </div>
340
+ <button class="${de}" data-action="save-settings" ${pe}>${ce}</button>
341
+ ${l}
342
+ </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}">${A(n.content)}</div>`).join(""),t=a.streaming?`<div class="om-msg om-msg-assistant"><span class="om-spinner"></span>${A(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 ie(){let e=f.querySelector(".om-chat-messages");e&&(e.scrollTop=e.scrollHeight)}async function $e(){let t=f.querySelector('[data-field="apiKey"]')?.value||"";if(!a.provider)return;let o={provider:a.provider,model:a.model};t&&(o.apiKey=t),a.saveStatus="saving",D();try{await v("config.set",o),a.hasApiKey=!!(t||a.hasApiKey),a.saveStatus="saved",D(),setTimeout(()=>{a.saveStatus="",a.activePanel==="settings"&&y("chat")},1200)}catch{a.saveStatus="error",D(),setTimeout(()=>{a.saveStatus="",C()},3e3)}}function D(){let e=f.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 re(){let e=x.value.trim();if(!e||a.streaming)return;if(!a.hasApiKey||!a.provider){y("settings");return}a.messages.push({role:"user",content:e}),a.streaming=!0,a.streamContent="",x.value="",y("chat");let t=Q(a.selectedElement,a.screenshot);t.pageUrl=window.location.href,t.pageTitle=document.title;try{let o=await q("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=f.querySelector(".om-msg-assistant:last-child");i&&(i.innerHTML=`<span class="om-spinner"></span>${A(a.streamContent)}`,ie())});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:oe(n.file)})).payload?.content;s?.includes(n.search)&&(await v("fs.write",{path:oe(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="",C()}function oe(e){return a.roots.length>0?a.roots[0]+"/"+e:e}var k=null,S=null;function He(){a.selecting?le():Pe()}function Pe(){a.selecting=!0,document.body.style.cursor="crosshair",L(),S=e=>{let t=e.target;if(t.closest("openmagic-toolbar")||t.dataset?.openmagic)return;let o=t.getBoundingClientRect();U({x:o.x,y:o.y,width:o.width,height:o.height})},k=e=>{e.preventDefault(),e.stopPropagation();let t=e.target;t.closest("openmagic-toolbar")||t.dataset?.openmagic||(a.selectedElement=z(t),le(),T(),x.focus())},document.addEventListener("mousemove",S,!0),document.addEventListener("click",k,!0)}function le(){a.selecting=!1,document.body.style.cursor="",G(),S&&(document.removeEventListener("mousemove",S,!0),S=null),k&&(document.removeEventListener("click",k,!0),k=null),L()}async function Ne(){let e=await I();e&&(a.screenshot=e,T(),x.focus())}function _e(){let e=!1,t=0,o=0,n=0,i=0;m.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=m.getBoundingClientRect();n=l.left,i=l.top,s.preventDefault()}),document.addEventListener("mousemove",s=>{if(!e)return;m.style.left=n+s.clientX-t+"px",m.style.top=i+s.clientY-o+"px",m.style.right="auto",m.style.bottom="auto";let r=m.getBoundingClientRect();w.style.right="auto",w.style.bottom="auto",w.style.left=r.left+"px",w.style.top=r.top-42+"px",u.style.right="auto",u.style.bottom="auto",u.style.left=r.left+"px",u.style.top=r.top-42-(u.classList.contains("om-hidden")?0:u.offsetHeight+6)+"px"}),document.addEventListener("mouseup",()=>{e=!1})}function A(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=ne.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(h.querySelector(".om-update-dot"))return;let t=document.createElement("span");t.className="om-update-dot",t.title=`v${a.latestVersion} available`,t.addEventListener("click",()=>y("settings")),m.appendChild(t)}typeof window<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Z):Z());})();
774
343
  //# sourceMappingURL=index.global.js.map