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