vite-plugin-opencode-assistant 1.0.12 → 1.0.14
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.
- package/es/client/index.js +424 -84
- package/es/core/api.d.ts +1 -0
- package/es/core/api.js +97 -15
- package/es/core/service.d.ts +8 -1
- package/es/core/service.js +84 -16
- package/es/endpoints/index.js +2 -0
- package/es/endpoints/sse.js +14 -5
- package/es/endpoints/types.d.ts +7 -1
- package/es/endpoints/warmup.d.ts +3 -0
- package/es/endpoints/warmup.js +45 -0
- package/es/index.js +12 -3
- package/lib/client/index.js +420 -83
- package/lib/client.js +3005 -2707
- package/lib/core/api.d.ts +1 -0
- package/lib/core/api.js +97 -15
- package/lib/core/service.d.ts +8 -1
- package/lib/core/service.js +83 -16
- package/lib/endpoints/index.js +2 -0
- package/lib/endpoints/sse.js +14 -5
- package/lib/endpoints/types.d.ts +7 -1
- package/lib/endpoints/warmup.d.ts +3 -0
- package/lib/endpoints/warmup.js +68 -0
- package/lib/index.js +12 -3
- package/lib/style.css +1 -1
- package/package.json +5 -5
package/es/client/index.js
CHANGED
|
@@ -40,7 +40,28 @@ var __async = (__this, __arguments, generator) => {
|
|
|
40
40
|
import { createApp, ref, watch, onMounted, h, computed } from "vue";
|
|
41
41
|
import { OpenCodeWidget } from "@vite-plugin-opencode-assistant/components";
|
|
42
42
|
import "@vite-plugin-opencode-assistant/components/style.css";
|
|
43
|
-
import {
|
|
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
|
+
}
|
|
44
65
|
function utf8ToBase64(str) {
|
|
45
66
|
const bytes = new TextEncoder().encode(str);
|
|
46
67
|
const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
|
|
@@ -83,13 +104,40 @@ const App = {
|
|
|
83
104
|
const sessions = ref([]);
|
|
84
105
|
const selectedElements = ref([]);
|
|
85
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
|
+
});
|
|
86
135
|
const {
|
|
87
136
|
position = "bottom-right",
|
|
88
137
|
theme: initialTheme = "auto",
|
|
89
138
|
open: autoOpen = false,
|
|
90
|
-
sessionUrl
|
|
139
|
+
// sessionUrl 不再从配置读取,完全依赖 SSE 状态同步
|
|
91
140
|
proxyUrl: configProxyUrl = "",
|
|
92
|
-
lazy = false,
|
|
93
141
|
hotkey = "ctrl+k",
|
|
94
142
|
cwd = ""
|
|
95
143
|
} = config;
|
|
@@ -97,18 +145,16 @@ const App = {
|
|
|
97
145
|
proxyUrl = configProxyUrl;
|
|
98
146
|
}
|
|
99
147
|
const theme = ref(initialTheme);
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
|
|
148
|
+
const showSessionListSkeleton = computed(() => serviceStatus.value === "starting");
|
|
149
|
+
const iframeLoading = ref(false);
|
|
150
|
+
const computedLoading = computed(() => {
|
|
151
|
+
return serviceStatus.value === "starting" || iframeLoading.value;
|
|
152
|
+
});
|
|
103
153
|
const extractSessionId = (url) => {
|
|
104
154
|
if (!url) return null;
|
|
105
155
|
const match = url.match(/\/session\/([^/?]+)/);
|
|
106
156
|
return match ? match[1] : null;
|
|
107
157
|
};
|
|
108
|
-
currentSessionId.value = extractSessionId(initialSessionUrl);
|
|
109
|
-
if (servicesStarted && initialSessionUrl) {
|
|
110
|
-
iframeSrc.value = toProxyUrl(initialSessionUrl);
|
|
111
|
-
}
|
|
112
158
|
try {
|
|
113
159
|
const stored = sessionStorage.getItem("__opencode_selected_elements__");
|
|
114
160
|
if (stored) {
|
|
@@ -182,38 +228,96 @@ const App = {
|
|
|
182
228
|
const selectSession = (session) => {
|
|
183
229
|
if (currentSessionId.value === session.id) return;
|
|
184
230
|
currentSessionId.value = session.id;
|
|
185
|
-
|
|
231
|
+
iframeLoading.value = true;
|
|
186
232
|
iframeSrc.value = `${proxyUrl}/${utf8ToBase64(cwd)}/session/${session.id}`;
|
|
187
|
-
setTimeout(() => {
|
|
188
|
-
loading.value = false;
|
|
189
|
-
}, 500);
|
|
190
233
|
};
|
|
191
234
|
let sseConnection = null;
|
|
235
|
+
let sseRetryCount = 0;
|
|
236
|
+
const MAX_SSE_RETRIES = 10;
|
|
237
|
+
const SSE_RETRY_DELAY = 1e3;
|
|
192
238
|
const setupSSE = () => {
|
|
193
|
-
if (
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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 = [];
|
|
204
294
|
}
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
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";
|
|
208
303
|
}
|
|
209
|
-
|
|
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);
|
|
210
314
|
}
|
|
211
|
-
}
|
|
315
|
+
}
|
|
212
316
|
};
|
|
213
317
|
let currentPageUrl = "";
|
|
214
318
|
let currentPageTitle = "";
|
|
215
319
|
const updateContext = (force = false) => {
|
|
216
|
-
if (
|
|
320
|
+
if (serviceStatus.value === "idle") return;
|
|
217
321
|
const newUrl = window.location.href;
|
|
218
322
|
const newTitle = document.title;
|
|
219
323
|
if (force || newUrl !== currentPageUrl || newTitle !== currentPageTitle) {
|
|
@@ -232,17 +336,12 @@ const App = {
|
|
|
232
336
|
}
|
|
233
337
|
};
|
|
234
338
|
const ensureServicesStarted = () => __async(null, null, function* () {
|
|
235
|
-
if (
|
|
339
|
+
if (serviceStatus.value !== "idle") return true;
|
|
236
340
|
try {
|
|
237
341
|
const res = yield fetch("/__opencode_start__");
|
|
238
342
|
const data = yield res.json();
|
|
239
343
|
if (data.success) {
|
|
240
|
-
|
|
241
|
-
if (data.sessionUrl) {
|
|
242
|
-
iframeSrc.value = toProxyUrl(data.sessionUrl);
|
|
243
|
-
currentSessionId.value = extractSessionId(data.sessionUrl);
|
|
244
|
-
isWaitingForSession.value = false;
|
|
245
|
-
}
|
|
344
|
+
serviceStatus.value = "starting";
|
|
246
345
|
setupSSE();
|
|
247
346
|
return true;
|
|
248
347
|
}
|
|
@@ -250,38 +349,62 @@ const App = {
|
|
|
250
349
|
}
|
|
251
350
|
return false;
|
|
252
351
|
});
|
|
352
|
+
const mainHotkey = parseHotkey(hotkey);
|
|
353
|
+
const selectHotkey = parseHotkey("ctrl+p");
|
|
253
354
|
onMounted(() => {
|
|
254
|
-
if (
|
|
355
|
+
if (serviceStatus.value !== "idle") {
|
|
255
356
|
loadSessions();
|
|
256
357
|
setupSSE();
|
|
257
358
|
updateContext(true);
|
|
258
359
|
}
|
|
259
|
-
if (autoOpen &&
|
|
360
|
+
if (autoOpen && serviceStatus.value !== "idle") {
|
|
260
361
|
setTimeout(() => {
|
|
261
362
|
open.value = true;
|
|
262
363
|
}, 1e3);
|
|
263
364
|
}
|
|
264
365
|
const originalPushState = history.pushState;
|
|
265
366
|
const originalReplaceState = history.replaceState;
|
|
367
|
+
const scheduleContextUpdate = () => {
|
|
368
|
+
requestAnimationFrame(() => updateContext());
|
|
369
|
+
};
|
|
266
370
|
history.pushState = function(...args) {
|
|
267
371
|
originalPushState.apply(this, args);
|
|
268
|
-
|
|
372
|
+
scheduleContextUpdate();
|
|
269
373
|
};
|
|
270
374
|
history.replaceState = function(...args) {
|
|
271
375
|
originalReplaceState.apply(this, args);
|
|
272
|
-
|
|
376
|
+
scheduleContextUpdate();
|
|
273
377
|
};
|
|
274
|
-
window.addEventListener("popstate",
|
|
275
|
-
window.addEventListener("hashchange",
|
|
378
|
+
window.addEventListener("popstate", scheduleContextUpdate);
|
|
379
|
+
window.addEventListener("hashchange", scheduleContextUpdate);
|
|
276
380
|
const titleObserver = new MutationObserver(() => {
|
|
277
381
|
if (document.title !== currentPageTitle) updateContext();
|
|
278
382
|
});
|
|
279
383
|
if (document.head) {
|
|
280
384
|
titleObserver.observe(document.head, { childList: true, subtree: true });
|
|
281
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
|
+
};
|
|
282
405
|
});
|
|
283
406
|
const handleToggle = (val) => __async(null, null, function* () {
|
|
284
|
-
if (
|
|
407
|
+
if (serviceStatus.value === "idle" && val) {
|
|
285
408
|
loading.value = true;
|
|
286
409
|
const started = yield ensureServicesStarted();
|
|
287
410
|
loading.value = false;
|
|
@@ -292,6 +415,9 @@ const App = {
|
|
|
292
415
|
}
|
|
293
416
|
open.value = val;
|
|
294
417
|
if (val) updateContext();
|
|
418
|
+
if (val) {
|
|
419
|
+
iframeLoading.value = false;
|
|
420
|
+
}
|
|
295
421
|
});
|
|
296
422
|
const handleSelectNode = (element) => {
|
|
297
423
|
const exists = selectedElements.value.some(
|
|
@@ -311,45 +437,116 @@ const App = {
|
|
|
311
437
|
showNotification("\u5DF2\u6E05\u9664\u6240\u6709\u9009\u4E2D\u5143\u7D20");
|
|
312
438
|
};
|
|
313
439
|
return () => {
|
|
314
|
-
return h(
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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
|
+
}
|
|
350
488
|
},
|
|
351
|
-
|
|
352
|
-
|
|
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
|
+
);
|
|
353
550
|
};
|
|
354
551
|
}
|
|
355
552
|
};
|
|
@@ -358,5 +555,148 @@ if (!window[INIT_MARKER]) {
|
|
|
358
555
|
window[INIT_MARKER] = true;
|
|
359
556
|
const container = document.createElement("div");
|
|
360
557
|
document.body.appendChild(container);
|
|
361
|
-
createApp(App)
|
|
558
|
+
const app = createApp(App);
|
|
559
|
+
app.mount(container);
|
|
560
|
+
window.__OPENCODE_CLEANUP__ = () => {
|
|
561
|
+
app.unmount();
|
|
562
|
+
container.remove();
|
|
563
|
+
window[INIT_MARKER] = false;
|
|
564
|
+
};
|
|
565
|
+
}
|
|
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;
|
|
362
700
|
}
|
|
701
|
+
`;
|
|
702
|
+
document.head.appendChild(style);
|
package/es/core/api.d.ts
CHANGED