vite-plugin-opencode-assistant 1.0.15 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/es/client/App.vue.d.ts +6 -0
  2. package/es/client/App.vue.js +300 -0
  3. package/es/client/components/ChromeWarmupError-sfc.css +1 -0
  4. package/es/client/components/ChromeWarmupError.vue.d.ts +11 -0
  5. package/es/client/components/ChromeWarmupError.vue.js +196 -0
  6. package/es/client/components/LoadingContent.vue.d.ts +5 -0
  7. package/es/client/components/LoadingContent.vue.js +39 -0
  8. package/es/client/composables/useContext.d.ts +8 -0
  9. package/es/client/composables/useContext.js +63 -0
  10. package/es/client/composables/useHotkey.d.ts +12 -0
  11. package/es/client/composables/useHotkey.js +41 -0
  12. package/es/client/composables/useSSE.d.ts +20 -0
  13. package/es/client/composables/useSSE.js +61 -0
  14. package/es/client/composables/useSelectedElements.d.ts +19 -0
  15. package/es/client/composables/useSelectedElements.js +43 -0
  16. package/es/client/composables/useServiceStatus.d.ts +13 -0
  17. package/es/client/composables/useServiceStatus.js +53 -0
  18. package/es/client/composables/useSessions.d.ts +26 -0
  19. package/es/client/composables/useSessions.js +127 -0
  20. package/es/client/composables/useTheme.d.ts +12 -0
  21. package/es/client/composables/useTheme.js +42 -0
  22. package/es/client/index.d.ts +1 -1
  23. package/es/client/index.js +5 -675
  24. package/es/client/styles.css +1 -0
  25. package/es/core/api.d.ts +18 -6
  26. package/es/core/api.js +324 -69
  27. package/es/core/proxy-server.js +127 -2
  28. package/es/core/service.d.ts +9 -2
  29. package/es/core/service.js +35 -31
  30. package/es/endpoints/index.js +1 -1
  31. package/es/endpoints/sse.js +0 -3
  32. package/es/endpoints/start.d.ts +1 -2
  33. package/es/endpoints/start.js +2 -2
  34. package/es/endpoints/types.d.ts +5 -2
  35. package/es/endpoints/warmup.js +15 -3
  36. package/es/index.js +8 -12
  37. package/es/utils/system.d.ts +1 -0
  38. package/es/utils/system.js +28 -0
  39. package/lib/client/App.vue.d.ts +6 -0
  40. package/lib/client/App.vue.js +329 -0
  41. package/lib/client/components/ChromeWarmupError-sfc.css +1 -0
  42. package/lib/client/components/ChromeWarmupError.vue.d.ts +11 -0
  43. package/lib/client/components/ChromeWarmupError.vue.js +215 -0
  44. package/lib/client/components/LoadingContent.vue.d.ts +5 -0
  45. package/lib/client/components/LoadingContent.vue.js +58 -0
  46. package/lib/client/composables/useContext.d.ts +8 -0
  47. package/lib/client/composables/useContext.js +86 -0
  48. package/lib/client/composables/useHotkey.d.ts +12 -0
  49. package/lib/client/composables/useHotkey.js +66 -0
  50. package/lib/client/composables/useSSE.d.ts +20 -0
  51. package/lib/client/composables/useSSE.js +84 -0
  52. package/lib/client/composables/useSelectedElements.d.ts +19 -0
  53. package/lib/client/composables/useSelectedElements.js +66 -0
  54. package/lib/client/composables/useServiceStatus.d.ts +13 -0
  55. package/lib/client/composables/useServiceStatus.js +76 -0
  56. package/lib/client/composables/useSessions.d.ts +26 -0
  57. package/lib/client/composables/useSessions.js +148 -0
  58. package/lib/client/composables/useTheme.d.ts +12 -0
  59. package/lib/client/composables/useTheme.js +65 -0
  60. package/lib/client/index.d.ts +1 -1
  61. package/lib/client/index.js +22 -667
  62. package/lib/client/styles.css +1 -0
  63. package/lib/client.js +2988 -2973
  64. package/lib/core/api.d.ts +18 -6
  65. package/lib/core/api.js +321 -74
  66. package/lib/core/proxy-server.js +127 -2
  67. package/lib/core/service.d.ts +9 -2
  68. package/lib/core/service.js +31 -30
  69. package/lib/endpoints/index.js +1 -1
  70. package/lib/endpoints/sse.js +0 -3
  71. package/lib/endpoints/start.d.ts +1 -2
  72. package/lib/endpoints/start.js +2 -2
  73. package/lib/endpoints/types.d.ts +5 -2
  74. package/lib/endpoints/warmup.js +15 -3
  75. package/lib/index.js +8 -12
  76. package/lib/style.css +1 -1
  77. package/lib/utils/system.d.ts +1 -0
  78. package/lib/utils/system.js +29 -0
  79. package/package.json +4 -4
@@ -1,82 +1,7 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- var __async = (__this, __arguments, generator) => {
21
- return new Promise((resolve, reject) => {
22
- var fulfilled = (value) => {
23
- try {
24
- step(generator.next(value));
25
- } catch (e) {
26
- reject(e);
27
- }
28
- };
29
- var rejected = (value) => {
30
- try {
31
- step(generator.throw(value));
32
- } catch (e) {
33
- reject(e);
34
- }
35
- };
36
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
- step((generator = generator.apply(__this, __arguments)).next());
38
- });
39
- };
40
- import { createApp, ref, watch, onMounted, h, computed } from "vue";
41
- import { OpenCodeWidget } from "@vite-plugin-opencode-assistant/components";
42
- import "@vite-plugin-opencode-assistant/components/style.css";
43
- import {
44
- CONFIG_DATA_ATTR,
45
- SERVICE_STARTUP_TASKS
46
- } from "@vite-plugin-opencode-assistant/shared";
47
- function parseHotkey(hotkeyStr) {
48
- if (!hotkeyStr) return { ctrl: true, shift: false, alt: false, key: "k" };
49
- const parts = hotkeyStr.toLowerCase().split("+");
50
- const key = parts.pop();
51
- return {
52
- ctrl: parts.includes("ctrl") || parts.includes("cmd") || parts.includes("meta"),
53
- shift: parts.includes("shift"),
54
- alt: parts.includes("alt"),
55
- key: key || "k"
56
- };
57
- }
58
- function matchHotkey(e, hotkeyConfig) {
59
- const ctrlMatch = hotkeyConfig.ctrl ? e.ctrlKey || e.metaKey : !(e.ctrlKey || e.metaKey);
60
- const shiftMatch = hotkeyConfig.shift ? e.shiftKey : !e.shiftKey;
61
- const altMatch = hotkeyConfig.alt ? e.altKey : !e.altKey;
62
- const keyMatch = e.key.toLowerCase() === hotkeyConfig.key.toLowerCase();
63
- return ctrlMatch && shiftMatch && altMatch && keyMatch;
64
- }
65
- function utf8ToBase64(str) {
66
- const bytes = new TextEncoder().encode(str);
67
- const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
68
- return btoa(binString);
69
- }
70
- let proxyUrl = "";
71
- function toProxyUrl(url) {
72
- if (!url || !proxyUrl) return url;
73
- try {
74
- const urlObj = new URL(url, window.location.origin);
75
- return `${proxyUrl}${urlObj.pathname}${urlObj.search}`;
76
- } catch (e) {
77
- return url;
78
- }
79
- }
1
+ import { createApp } from "vue";
2
+ import { CONFIG_DATA_ATTR } from "@vite-plugin-opencode-assistant/shared";
3
+ import App from "./App.vue.js";
4
+ import "./styles.css";
80
5
  let config = {};
81
6
  const scriptTag = document.querySelector(`script[${CONFIG_DATA_ATTR}]`);
82
7
  if (scriptTag) {
@@ -92,470 +17,12 @@ if (scriptTag) {
92
17
  }
93
18
  }
94
19
  }
95
- const App = {
96
- setup() {
97
- const open = ref(false);
98
- const selectMode = ref(false);
99
- const sessionListCollapsed = ref(true);
100
- const loading = ref(false);
101
- const loadingSessionList = ref(void 0);
102
- const iframeSrc = ref("");
103
- const currentSessionId = ref(null);
104
- const sessions = ref([]);
105
- const selectedElements = ref([]);
106
- const widgetRef = ref(null);
107
- const chromeMcpFailed = ref(false);
108
- const currentTask = ref("");
109
- const serviceStatus = ref("idle");
110
- const loadingText = computed(() => {
111
- if (iframeLoading.value) return "\u52A0\u8F7D\u4E2D...";
112
- if (!currentTask.value) return "\u52A0\u8F7D\u4E2D...";
113
- return SERVICE_STARTUP_TASKS[currentTask.value] || "\u52A0\u8F7D\u4E2D...";
114
- });
115
- const retryingWarmup = ref(false);
116
- const retryWarmup = () => __async(null, null, function* () {
117
- retryingWarmup.value = true;
118
- try {
119
- const res = yield fetch("/__opencode_warmup__", { method: "POST" });
120
- const data = yield res.json();
121
- if (data.success) {
122
- chromeMcpFailed.value = false;
123
- serviceStatus.value = "ready";
124
- showNotification("Chrome DevTools MCP \u8FDE\u63A5\u6210\u529F");
125
- } else {
126
- showNotification(data.error || "\u91CD\u8BD5\u5931\u8D25\uFF0C\u8BF7\u786E\u8BA4 Chrome \u8FDC\u7A0B\u8C03\u8BD5\u5DF2\u5F00\u542F");
127
- }
128
- } catch (e) {
129
- console.error("[OpenCode] Retry warmup failed:", e);
130
- showNotification("\u91CD\u8BD5\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5");
131
- } finally {
132
- retryingWarmup.value = false;
133
- }
134
- });
135
- const {
136
- position = "bottom-right",
137
- theme: initialTheme = "auto",
138
- open: autoOpen = false,
139
- // sessionUrl 不再从配置读取,完全依赖 SSE 状态同步
140
- proxyUrl: configProxyUrl = "",
141
- hotkey = "ctrl+k",
142
- cwd = ""
143
- } = config;
144
- if (configProxyUrl) {
145
- proxyUrl = configProxyUrl;
146
- }
147
- const theme = ref(initialTheme);
148
- const showSessionListSkeleton = computed(() => serviceStatus.value === "starting");
149
- const iframeLoading = ref(false);
150
- const computedLoading = computed(() => {
151
- return serviceStatus.value === "starting" || iframeLoading.value;
152
- });
153
- const extractSessionId = (url) => {
154
- if (!url) return null;
155
- const match = url.match(/\/session\/([^/?]+)/);
156
- return match ? match[1] : null;
157
- };
158
- try {
159
- const stored = sessionStorage.getItem("__opencode_selected_elements__");
160
- if (stored) {
161
- selectedElements.value = JSON.parse(stored);
162
- }
163
- } catch (e) {
164
- }
165
- watch(
166
- selectedElements,
167
- (val) => {
168
- sessionStorage.setItem("__opencode_selected_elements__", JSON.stringify(val));
169
- },
170
- { deep: true }
171
- );
172
- const showNotification = (msg) => {
173
- var _a, _b;
174
- (_b = (_a = widgetRef.value) == null ? void 0 : _a.showNotification) == null ? void 0 : _b.call(_a, msg);
175
- };
176
- const loadSessions = () => __async(null, null, function* () {
177
- loadingSessionList.value = true;
178
- try {
179
- const response = yield fetch("/__opencode_sessions__");
180
- const data = yield response.json();
181
- sessions.value = data.filter((s) => s.directory === cwd && s.title !== "__chrome_mcp_warmup__").map((s) => {
182
- var _a;
183
- return __spreadProps(__spreadValues({}, s), {
184
- updatedAt: ((_a = s.time) == null ? void 0 : _a.updated) || Date.now()
185
- });
186
- });
187
- } catch (e) {
188
- console.error("[OpenCode] Failed to load sessions:", e);
189
- } finally {
190
- loadingSessionList.value = false;
191
- }
192
- });
193
- const createSession = () => __async(null, null, function* () {
194
- try {
195
- const response = yield fetch("/__opencode_sessions__", { method: "POST" });
196
- const newSession = yield response.json();
197
- sessions.value.unshift({
198
- id: newSession.id,
199
- title: "\u65B0\u4F1A\u8BDD",
200
- updatedAt: Date.now()
201
- });
202
- currentSessionId.value = newSession.id;
203
- iframeSrc.value = `${proxyUrl}/${utf8ToBase64(cwd)}/session/${newSession.id}`;
204
- loadSessions();
205
- } catch (e) {
206
- showNotification("\u521B\u5EFA\u4F1A\u8BDD\u5931\u8D25");
207
- }
208
- });
209
- const deleteSession = (session) => __async(null, null, function* () {
210
- try {
211
- yield fetch(`/__opencode_sessions__?id=${session.id}`, { method: "DELETE" });
212
- yield loadSessions();
213
- showNotification("\u4F1A\u8BDD\u5DF2\u5220\u9664");
214
- if (currentSessionId.value === session.id) {
215
- if (sessions.value.length > 0) {
216
- const nextSession = sessions.value[0];
217
- currentSessionId.value = nextSession.id;
218
- iframeSrc.value = `${proxyUrl}/${utf8ToBase64(cwd)}/session/${nextSession.id}`;
219
- } else {
220
- currentSessionId.value = null;
221
- iframeSrc.value = "";
222
- }
223
- }
224
- } catch (e) {
225
- showNotification("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25");
226
- }
227
- });
228
- const selectSession = (session) => {
229
- if (currentSessionId.value === session.id) return;
230
- currentSessionId.value = session.id;
231
- iframeLoading.value = true;
232
- iframeSrc.value = `${proxyUrl}/${utf8ToBase64(cwd)}/session/${session.id}`;
233
- };
234
- let sseConnection = null;
235
- let sseRetryCount = 0;
236
- const MAX_SSE_RETRIES = 10;
237
- const SSE_RETRY_DELAY = 1e3;
238
- const setupSSE = () => {
239
- if (sseConnection) return;
240
- try {
241
- sseConnection = new EventSource("/__opencode_events__");
242
- sseConnection.onmessage = (event) => {
243
- try {
244
- const data = JSON.parse(event.data);
245
- if (data.type === "CONNECTED") {
246
- updateContext(true);
247
- sseRetryCount = 0;
248
- } else if (data.type === "STATUS_SYNC") {
249
- if (data.isStarted !== void 0) {
250
- if (data.isStarted && serviceStatus.value === "idle") {
251
- serviceStatus.value = "starting";
252
- }
253
- }
254
- if (data.task) {
255
- currentTask.value = data.task;
256
- if (data.task === "ready") {
257
- serviceStatus.value = "ready";
258
- chromeMcpFailed.value = false;
259
- if (data.sessionUrl && !iframeSrc.value) {
260
- iframeSrc.value = toProxyUrl(data.sessionUrl);
261
- currentSessionId.value = extractSessionId(data.sessionUrl);
262
- }
263
- } else if (data.task === "chrome_mcp_failed") {
264
- serviceStatus.value = "partial";
265
- chromeMcpFailed.value = true;
266
- } else if (data.task === "session_creation_failed" || data.task === "opencode_not_installed" || data.task === "web_start_timeout") {
267
- serviceStatus.value = "failed";
268
- } else if (serviceStatus.value === "idle") {
269
- serviceStatus.value = "starting";
270
- }
271
- }
272
- if (serviceStatus.value !== "idle") {
273
- loadSessions();
274
- }
275
- } else if (data.type === "TASK_UPDATE") {
276
- currentTask.value = data.task;
277
- if (data.task === "ready") {
278
- serviceStatus.value = "ready";
279
- chromeMcpFailed.value = false;
280
- if (data.sessionUrl && !iframeSrc.value) {
281
- iframeSrc.value = toProxyUrl(data.sessionUrl);
282
- currentSessionId.value = extractSessionId(data.sessionUrl);
283
- }
284
- } else if (data.task === "chrome_mcp_failed") {
285
- serviceStatus.value = "partial";
286
- chromeMcpFailed.value = true;
287
- } else if (data.task === "session_creation_failed" || data.task === "opencode_not_installed" || data.task === "web_start_timeout") {
288
- serviceStatus.value = "failed";
289
- } else if (serviceStatus.value === "idle") {
290
- serviceStatus.value = "starting";
291
- }
292
- } else if (data.type === "CLEAR_ELEMENTS") {
293
- selectedElements.value = [];
294
- }
295
- } catch (e) {
296
- }
297
- };
298
- sseConnection.onerror = () => {
299
- sseConnection == null ? void 0 : sseConnection.close();
300
- sseConnection = null;
301
- if (serviceStatus.value === "ready" || serviceStatus.value === "partial") {
302
- serviceStatus.value = "starting";
303
- }
304
- if (sseRetryCount < MAX_SSE_RETRIES) {
305
- sseRetryCount++;
306
- setTimeout(setupSSE, SSE_RETRY_DELAY * sseRetryCount);
307
- }
308
- };
309
- } catch (e) {
310
- sseConnection = null;
311
- if (sseRetryCount < MAX_SSE_RETRIES) {
312
- sseRetryCount++;
313
- setTimeout(setupSSE, SSE_RETRY_DELAY * sseRetryCount);
314
- }
315
- }
316
- };
317
- let currentPageUrl = "";
318
- let currentPageTitle = "";
319
- const updateContext = (force = false) => {
320
- if (serviceStatus.value === "idle") return;
321
- const newUrl = window.location.href;
322
- const newTitle = document.title;
323
- if (force || newUrl !== currentPageUrl || newTitle !== currentPageTitle) {
324
- currentPageUrl = newUrl;
325
- currentPageTitle = newTitle;
326
- fetch("/__opencode_context__", {
327
- method: "POST",
328
- headers: { "Content-Type": "application/json" },
329
- body: JSON.stringify({
330
- url: newUrl,
331
- title: newTitle,
332
- selectedElements: selectedElements.value
333
- })
334
- }).catch(() => {
335
- });
336
- }
337
- };
338
- const ensureServicesStarted = () => __async(null, null, function* () {
339
- if (serviceStatus.value !== "idle") return true;
340
- try {
341
- const res = yield fetch("/__opencode_start__");
342
- const data = yield res.json();
343
- if (data.success) {
344
- serviceStatus.value = "starting";
345
- setupSSE();
346
- return true;
347
- }
348
- } catch (e) {
349
- }
350
- return false;
351
- });
352
- const mainHotkey = parseHotkey(hotkey);
353
- const selectHotkey = parseHotkey("ctrl+p");
354
- onMounted(() => {
355
- if (serviceStatus.value !== "idle") {
356
- loadSessions();
357
- setupSSE();
358
- updateContext(true);
359
- }
360
- if (autoOpen && serviceStatus.value !== "idle") {
361
- setTimeout(() => {
362
- open.value = true;
363
- }, 1e3);
364
- }
365
- const originalPushState = history.pushState;
366
- const originalReplaceState = history.replaceState;
367
- const scheduleContextUpdate = () => {
368
- requestAnimationFrame(() => updateContext());
369
- };
370
- history.pushState = function(...args) {
371
- originalPushState.apply(this, args);
372
- scheduleContextUpdate();
373
- };
374
- history.replaceState = function(...args) {
375
- originalReplaceState.apply(this, args);
376
- scheduleContextUpdate();
377
- };
378
- window.addEventListener("popstate", scheduleContextUpdate);
379
- window.addEventListener("hashchange", scheduleContextUpdate);
380
- const titleObserver = new MutationObserver(() => {
381
- if (document.title !== currentPageTitle) updateContext();
382
- });
383
- if (document.head) {
384
- titleObserver.observe(document.head, { childList: true, subtree: true });
385
- }
386
- const handleKeydown = (e) => {
387
- if (matchHotkey(e, mainHotkey)) {
388
- e.preventDefault();
389
- handleToggle(!open.value);
390
- }
391
- if (matchHotkey(e, selectHotkey)) {
392
- e.preventDefault();
393
- const win = window;
394
- if (win.__VUE_INSPECTOR__) {
395
- selectMode.value = !selectMode.value;
396
- } else {
397
- showNotification("Vue Inspector \u672A\u52A0\u8F7D\uFF0C\u65E0\u6CD5\u4F7F\u7528\u5143\u7D20\u9009\u62E9\u529F\u80FD");
398
- }
399
- }
400
- };
401
- document.addEventListener("keydown", handleKeydown);
402
- return () => {
403
- document.removeEventListener("keydown", handleKeydown);
404
- };
405
- });
406
- const handleToggle = (val) => __async(null, null, function* () {
407
- if (serviceStatus.value === "idle" && val) {
408
- loading.value = true;
409
- const started = yield ensureServicesStarted();
410
- loading.value = false;
411
- if (!started) {
412
- showNotification("\u670D\u52A1\u542F\u52A8\u5931\u8D25");
413
- return;
414
- }
415
- }
416
- open.value = val;
417
- if (val) updateContext();
418
- if (val) {
419
- iframeLoading.value = false;
420
- }
421
- });
422
- const handleSelectNode = (element) => {
423
- const exists = selectedElements.value.some(
424
- (el) => el.filePath === element.filePath && el.line === element.line
425
- );
426
- if (!exists) {
427
- selectedElements.value.push(element);
428
- showNotification(`\u5DF2\u9009\u4E2D\u5143\u7D20 (${selectedElements.value.length}\u4E2A)`);
429
- updateContext(true);
430
- } else {
431
- showNotification("\u8BE5\u5143\u7D20\u5DF2\u9009\u4E2D");
432
- }
433
- };
434
- const handleClearSelected = () => {
435
- selectedElements.value = [];
436
- updateContext(true);
437
- showNotification("\u5DF2\u6E05\u9664\u6240\u6709\u9009\u4E2D\u5143\u7D20");
438
- };
439
- return () => {
440
- return h(
441
- OpenCodeWidget,
442
- {
443
- ref: widgetRef,
444
- position,
445
- theme: theme.value,
446
- open: open.value,
447
- selectMode: selectMode.value,
448
- sessionListCollapsed: sessionListCollapsed.value,
449
- frameLoading: computedLoading.value,
450
- loadingSessionList: loadingSessionList.value,
451
- showSessionListSkeleton: showSessionListSkeleton.value,
452
- showError: chromeMcpFailed.value,
453
- iframeSrc: iframeSrc.value,
454
- currentSessionId: currentSessionId.value,
455
- sessions: sessions.value,
456
- sessionKey: "id",
457
- selectedElements: selectedElements.value,
458
- hotkeyLabel: hotkey,
459
- "onUpdate:open": handleToggle,
460
- "onUpdate:selectMode": (val) => {
461
- selectMode.value = val;
462
- if (!val && !open.value) {
463
- open.value = true;
464
- }
465
- },
466
- "onUpdate:sessionListCollapsed": (val) => {
467
- sessionListCollapsed.value = val;
468
- },
469
- "onUpdate:theme": (val) => {
470
- theme.value = val;
471
- },
472
- "onToggle-theme": (val) => {
473
- theme.value = val;
474
- },
475
- "onCreate-session": createSession,
476
- "onDelete-session": deleteSession,
477
- "onSelect-session": selectSession,
478
- "onClick-selected-node": handleSelectNode,
479
- "onClear-selected-nodes": handleClearSelected,
480
- "onRemove-selected-node": ({ index }) => {
481
- selectedElements.value.splice(index, 1);
482
- updateContext(true);
483
- },
484
- "onEmpty-action": createSession,
485
- "onFrame-loaded": () => {
486
- iframeLoading.value = false;
487
- }
488
- },
489
- {
490
- loading: () => h("div", { class: "opencode-custom-loading" }, [
491
- h("div", { class: "opencode-loading-spinner" }),
492
- h("div", { class: "opencode-loading-text" }, loadingText.value)
493
- ]),
494
- error: () => chromeMcpFailed.value ? h("div", { class: "opencode-chrome-warmup-failed" }, [
495
- h("div", { class: "opencode-chrome-warmup-failed-icon" }, [
496
- h(
497
- "svg",
498
- {
499
- viewBox: "0 0 24 24",
500
- width: "48",
501
- height: "48",
502
- fill: "none",
503
- stroke: "currentColor",
504
- strokeWidth: "1.5"
505
- },
506
- [
507
- h("path", {
508
- strokeLinecap: "round",
509
- strokeLinejoin: "round",
510
- d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
511
- })
512
- ]
513
- )
514
- ]),
515
- h(
516
- "div",
517
- { class: "opencode-chrome-warmup-failed-title" },
518
- "Chrome DevTools MCP \u8FDE\u63A5\u5931\u8D25"
519
- ),
520
- h("div", { class: "opencode-chrome-warmup-failed-text" }, [
521
- h("p", {}, "\u8BF7\u6309\u4EE5\u4E0B\u6B65\u9AA4\u5F00\u542F Chrome \u8FDC\u7A0B\u8C03\u8BD5\uFF1A"),
522
- h("ol", { class: "opencode-chrome-warmup-steps" }, [
523
- h("li", {}, [
524
- "\u5728 Chrome \u5730\u5740\u680F\u8F93\u5165 ",
525
- h(
526
- "code",
527
- { class: "opencode-chrome-warmup-code" },
528
- "chrome://inspect/#remote-debugging"
529
- )
530
- ]),
531
- h("li", {}, "\u52FE\u9009 'Allow remote debugging for this browser instance' \u9009\u9879"),
532
- h("li", {}, "\u91CD\u65B0\u542F\u52A8\u6D4F\u89C8\u5668"),
533
- h("li", {}, "\u5B8C\u6210\u540E\u70B9\u51FB\u4E0B\u65B9\u6309\u94AE\u91CD\u8BD5")
534
- ])
535
- ]),
536
- h("div", { class: "opencode-chrome-warmup-failed-actions" }, [
537
- h(
538
- "button",
539
- {
540
- class: "opencode-chrome-warmup-failed-btn primary",
541
- disabled: retryingWarmup.value,
542
- onClick: retryWarmup
543
- },
544
- retryingWarmup.value ? "\u8FDE\u63A5\u4E2D..." : "\u91CD\u8BD5\u8FDE\u63A5"
545
- )
546
- ])
547
- ]) : null
548
- }
549
- );
550
- };
551
- }
552
- };
553
20
  const INIT_MARKER = "__OPENCODE_INITIALIZED__";
554
21
  if (!window[INIT_MARKER]) {
555
22
  window[INIT_MARKER] = true;
556
23
  const container = document.createElement("div");
557
24
  document.body.appendChild(container);
558
- const app = createApp(App);
25
+ const app = createApp(App, { config });
559
26
  app.mount(container);
560
27
  window.__OPENCODE_CLEANUP__ = () => {
561
28
  app.unmount();
@@ -563,140 +30,3 @@ if (!window[INIT_MARKER]) {
563
30
  window[INIT_MARKER] = false;
564
31
  };
565
32
  }
566
- const style = document.createElement("style");
567
- style.textContent = `
568
- .opencode-custom-loading {
569
- display: flex;
570
- flex-direction: column;
571
- align-items: center;
572
- justify-content: center;
573
- padding: 20px;
574
- }
575
-
576
- .opencode-loading-spinner {
577
- width: 32px;
578
- height: 32px;
579
- border: 3px solid var(--oc-border);
580
- border-top-color: var(--oc-primary);
581
- border-radius: 50%;
582
- animation: opencode-spin 0.8s linear infinite;
583
- }
584
-
585
- @keyframes opencode-spin {
586
- to { transform: rotate(360deg); }
587
- }
588
-
589
- .opencode-loading-text {
590
- margin-top: 12px;
591
- color: var(--oc-text-secondary);
592
- font-size: 14px;
593
- }
594
-
595
- .opencode-chrome-warmup-failed {
596
- position: absolute;
597
- top: 0;
598
- left: 0;
599
- right: 0;
600
- bottom: 0;
601
- background: var(--oc-bg-secondary);
602
- display: flex;
603
- flex-direction: column;
604
- align-items: center;
605
- justify-content: center;
606
- z-index: 15;
607
- }
608
-
609
- .opencode-chrome-warmup-failed-icon {
610
- color: var(--oc-warning, #f59e0b);
611
- margin-bottom: 16px;
612
- }
613
-
614
- .opencode-chrome-warmup-failed-title {
615
- color: var(--oc-text-primary);
616
- font-size: 18px;
617
- font-weight: 600;
618
- margin-bottom: 8px;
619
- }
620
-
621
- .opencode-chrome-warmup-failed-text {
622
- color: var(--oc-text-secondary);
623
- font-size: 14px;
624
- margin-bottom: 24px;
625
- text-align: left;
626
- max-width: 400px;
627
- line-height: 1.6;
628
- text-align: center;
629
- }
630
-
631
- .opencode-chrome-warmup-failed-text p {
632
- margin: 0 0 12px 0;
633
- font-weight: 500;
634
- color: var(--oc-text-primary);
635
- }
636
-
637
- .opencode-chrome-warmup-steps {
638
- margin: 0;
639
- padding-left: 20px;
640
- }
641
-
642
- .opencode-chrome-warmup-steps li {
643
- margin-bottom: 8px;
644
- color: var(--oc-text-secondary);
645
- font-size: 13px;
646
- line-height: 1.5;
647
- }
648
-
649
- .opencode-chrome-warmup-steps li:last-child {
650
- margin-bottom: 0;
651
- }
652
-
653
- .opencode-chrome-warmup-code {
654
- display: inline-block;
655
- background: var(--oc-bg-tertiary);
656
- color: var(--oc-primary);
657
- padding: 2px 6px;
658
- border-radius: 4px;
659
- font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
660
- font-size: 12px;
661
- font-weight: 500;
662
- word-break: break-all;
663
- margin: 0 2px;
664
- }
665
-
666
- .opencode-chrome-warmup-failed-actions {
667
- display: flex;
668
- gap: 12px;
669
- }
670
-
671
- .opencode-chrome-warmup-failed-btn {
672
- padding: 10px 24px;
673
- border-radius: 8px;
674
- border: none;
675
- font-size: 14px;
676
- font-weight: 500;
677
- cursor: pointer;
678
- transition: all 0.2s;
679
- }
680
-
681
- .opencode-chrome-warmup-failed-btn.primary {
682
- background: var(--oc-primary);
683
- color: white;
684
- box-shadow: var(--oc-shadow-primary);
685
- }
686
-
687
- .opencode-chrome-warmup-failed-btn.primary:hover:not(:disabled) {
688
- background: var(--oc-primary-hover);
689
- transform: translateY(-1px);
690
- box-shadow: var(--oc-shadow-primary-hover);
691
- }
692
-
693
- .opencode-chrome-warmup-failed-btn.primary:active:not(:disabled) {
694
- transform: translateY(0);
695
- }
696
-
697
- .opencode-chrome-warmup-failed-btn:disabled {
698
- opacity: 0.6;
699
- cursor: not-allowed;
700
- }
701
- `;
702
- document.head.appendChild(style);
@@ -0,0 +1 @@
1
+ .opencode-custom-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px}.opencode-loading-spinner{width:32px;height:32px;border:3px solid var(--oc-border-primary);border-top-color:var(--oc-primary);border-radius:50%;animation:opencode-spin .8s linear infinite}@keyframes opencode-spin{to{transform:rotate(360deg)}}.opencode-loading-text{margin-top:12px;color:var(--oc-text-secondary);font-size:14px}.opencode-chrome-warmup-failed{position:absolute;top:0;left:0;right:0;bottom:0;background:var(--oc-bg-secondary);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:15}.opencode-chrome-warmup-failed-icon{color:var(--oc-warning, #f59e0b);margin-bottom:16px}.opencode-chrome-warmup-failed-title{color:var(--oc-text-primary);font-size:18px;font-weight:600;margin-bottom:8px}.opencode-chrome-warmup-failed-text{color:var(--oc-text-secondary);font-size:14px;margin-bottom:24px;text-align:left;max-width:400px;line-height:1.6;text-align:center}.opencode-chrome-warmup-failed-text p{margin:0 0 12px;font-weight:500;color:var(--oc-text-primary)}.opencode-chrome-warmup-steps{margin:0;padding-left:20px}.opencode-chrome-warmup-steps li{margin-bottom:8px;color:var(--oc-text-secondary);font-size:13px;line-height:1.5}.opencode-chrome-warmup-steps li:last-child{margin-bottom:0}.opencode-chrome-warmup-code{display:inline-block;background:var(--oc-bg-tertiary);color:var(--oc-primary);padding:2px 6px;border-radius:4px;font-family:Monaco,Menlo,Ubuntu Mono,monospace;font-size:12px;font-weight:500;word-break:break-all;margin:0 2px}.opencode-chrome-warmup-failed-actions{display:flex;gap:12px}.opencode-chrome-warmup-failed-btn{padding:10px 24px;border-radius:8px;border:none;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s}.opencode-chrome-warmup-failed-btn.primary{background:var(--oc-primary);color:#fff;box-shadow:var(--oc-shadow-primary)}.opencode-chrome-warmup-failed-btn.primary:hover:not(:disabled){background:var(--oc-primary-hover);transform:translateY(-1px);box-shadow:var(--oc-shadow-primary-hover)}.opencode-chrome-warmup-failed-btn.primary:active:not(:disabled){transform:translateY(0)}.opencode-chrome-warmup-failed-btn.primary:disabled{opacity:.6;cursor:not-allowed}