vite-plugin-opencode-assistant 1.0.13 → 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.
@@ -40,7 +40,10 @@ 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 { CONFIG_DATA_ATTR } from "@vite-plugin-opencode-assistant/shared";
43
+ import {
44
+ CONFIG_DATA_ATTR,
45
+ SERVICE_STARTUP_TASKS
46
+ } from "@vite-plugin-opencode-assistant/shared";
44
47
  function parseHotkey(hotkeyStr) {
45
48
  if (!hotkeyStr) return { ctrl: true, shift: false, alt: false, key: "k" };
46
49
  const parts = hotkeyStr.toLowerCase().split("+");
@@ -101,13 +104,40 @@ const App = {
101
104
  const sessions = ref([]);
102
105
  const selectedElements = ref([]);
103
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
+ });
104
135
  const {
105
136
  position = "bottom-right",
106
137
  theme: initialTheme = "auto",
107
138
  open: autoOpen = false,
108
- sessionUrl: initialSessionUrl = "",
139
+ // sessionUrl 不再从配置读取,完全依赖 SSE 状态同步
109
140
  proxyUrl: configProxyUrl = "",
110
- lazy = false,
111
141
  hotkey = "ctrl+k",
112
142
  cwd = ""
113
143
  } = config;
@@ -115,18 +145,16 @@ const App = {
115
145
  proxyUrl = configProxyUrl;
116
146
  }
117
147
  const theme = ref(initialTheme);
118
- const isWaitingForSession = ref(!initialSessionUrl);
119
- const computedLoading = computed(() => loading.value || isWaitingForSession.value);
120
- let servicesStarted = !lazy;
148
+ const showSessionListSkeleton = computed(() => serviceStatus.value === "starting");
149
+ const iframeLoading = ref(false);
150
+ const computedLoading = computed(() => {
151
+ return serviceStatus.value === "starting" || iframeLoading.value;
152
+ });
121
153
  const extractSessionId = (url) => {
122
154
  if (!url) return null;
123
155
  const match = url.match(/\/session\/([^/?]+)/);
124
156
  return match ? match[1] : null;
125
157
  };
126
- currentSessionId.value = extractSessionId(initialSessionUrl);
127
- if (servicesStarted && initialSessionUrl) {
128
- iframeSrc.value = toProxyUrl(initialSessionUrl);
129
- }
130
158
  try {
131
159
  const stored = sessionStorage.getItem("__opencode_selected_elements__");
132
160
  if (stored) {
@@ -200,38 +228,96 @@ const App = {
200
228
  const selectSession = (session) => {
201
229
  if (currentSessionId.value === session.id) return;
202
230
  currentSessionId.value = session.id;
203
- loading.value = true;
231
+ iframeLoading.value = true;
204
232
  iframeSrc.value = `${proxyUrl}/${utf8ToBase64(cwd)}/session/${session.id}`;
205
- setTimeout(() => {
206
- loading.value = false;
207
- }, 500);
208
233
  };
209
234
  let sseConnection = null;
235
+ let sseRetryCount = 0;
236
+ const MAX_SSE_RETRIES = 10;
237
+ const SSE_RETRY_DELAY = 1e3;
210
238
  const setupSSE = () => {
211
- if (!servicesStarted || sseConnection) return;
212
- sseConnection = new EventSource("/__opencode_events__");
213
- sseConnection.onmessage = (event) => {
214
- try {
215
- const data = JSON.parse(event.data);
216
- if (data.type === "CONNECTED") {
217
- updateContext(true);
218
- } else if (data.type === "SESSION_READY") {
219
- if (data.sessionUrl && !iframeSrc.value) {
220
- iframeSrc.value = toProxyUrl(data.sessionUrl);
221
- currentSessionId.value = extractSessionId(data.sessionUrl);
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 = [];
222
294
  }
223
- isWaitingForSession.value = false;
224
- } else if (data.type === "CLEAR_ELEMENTS") {
225
- selectedElements.value = [];
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";
226
303
  }
227
- } catch (e) {
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);
228
314
  }
229
- };
315
+ }
230
316
  };
231
317
  let currentPageUrl = "";
232
318
  let currentPageTitle = "";
233
319
  const updateContext = (force = false) => {
234
- if (!servicesStarted) return;
320
+ if (serviceStatus.value === "idle") return;
235
321
  const newUrl = window.location.href;
236
322
  const newTitle = document.title;
237
323
  if (force || newUrl !== currentPageUrl || newTitle !== currentPageTitle) {
@@ -250,17 +336,12 @@ const App = {
250
336
  }
251
337
  };
252
338
  const ensureServicesStarted = () => __async(null, null, function* () {
253
- if (servicesStarted) return true;
339
+ if (serviceStatus.value !== "idle") return true;
254
340
  try {
255
341
  const res = yield fetch("/__opencode_start__");
256
342
  const data = yield res.json();
257
343
  if (data.success) {
258
- servicesStarted = true;
259
- if (data.sessionUrl) {
260
- iframeSrc.value = toProxyUrl(data.sessionUrl);
261
- currentSessionId.value = extractSessionId(data.sessionUrl);
262
- isWaitingForSession.value = false;
263
- }
344
+ serviceStatus.value = "starting";
264
345
  setupSSE();
265
346
  return true;
266
347
  }
@@ -271,28 +352,31 @@ const App = {
271
352
  const mainHotkey = parseHotkey(hotkey);
272
353
  const selectHotkey = parseHotkey("ctrl+p");
273
354
  onMounted(() => {
274
- if (servicesStarted) {
355
+ if (serviceStatus.value !== "idle") {
275
356
  loadSessions();
276
357
  setupSSE();
277
358
  updateContext(true);
278
359
  }
279
- if (autoOpen && servicesStarted) {
360
+ if (autoOpen && serviceStatus.value !== "idle") {
280
361
  setTimeout(() => {
281
362
  open.value = true;
282
363
  }, 1e3);
283
364
  }
284
365
  const originalPushState = history.pushState;
285
366
  const originalReplaceState = history.replaceState;
367
+ const scheduleContextUpdate = () => {
368
+ requestAnimationFrame(() => updateContext());
369
+ };
286
370
  history.pushState = function(...args) {
287
371
  originalPushState.apply(this, args);
288
- setTimeout(updateContext, 0);
372
+ scheduleContextUpdate();
289
373
  };
290
374
  history.replaceState = function(...args) {
291
375
  originalReplaceState.apply(this, args);
292
- setTimeout(updateContext, 0);
376
+ scheduleContextUpdate();
293
377
  };
294
- window.addEventListener("popstate", () => setTimeout(updateContext, 0));
295
- window.addEventListener("hashchange", () => setTimeout(updateContext, 0));
378
+ window.addEventListener("popstate", scheduleContextUpdate);
379
+ window.addEventListener("hashchange", scheduleContextUpdate);
296
380
  const titleObserver = new MutationObserver(() => {
297
381
  if (document.title !== currentPageTitle) updateContext();
298
382
  });
@@ -320,7 +404,7 @@ const App = {
320
404
  };
321
405
  });
322
406
  const handleToggle = (val) => __async(null, null, function* () {
323
- if (lazy && !servicesStarted && val) {
407
+ if (serviceStatus.value === "idle" && val) {
324
408
  loading.value = true;
325
409
  const started = yield ensureServicesStarted();
326
410
  loading.value = false;
@@ -331,6 +415,9 @@ const App = {
331
415
  }
332
416
  open.value = val;
333
417
  if (val) updateContext();
418
+ if (val) {
419
+ iframeLoading.value = false;
420
+ }
334
421
  });
335
422
  const handleSelectNode = (element) => {
336
423
  const exists = selectedElements.value.some(
@@ -350,48 +437,116 @@ const App = {
350
437
  showNotification("\u5DF2\u6E05\u9664\u6240\u6709\u9009\u4E2D\u5143\u7D20");
351
438
  };
352
439
  return () => {
353
- return h(OpenCodeWidget, {
354
- ref: widgetRef,
355
- position,
356
- theme: theme.value,
357
- open: open.value,
358
- selectMode: selectMode.value,
359
- sessionListCollapsed: sessionListCollapsed.value,
360
- loading: computedLoading.value,
361
- loadingSessionList: loadingSessionList.value,
362
- iframeSrc: iframeSrc.value,
363
- currentSessionId: currentSessionId.value,
364
- sessions: sessions.value,
365
- sessionKey: "id",
366
- selectedElements: selectedElements.value,
367
- hotkeyLabel: hotkey,
368
- "onUpdate:open": handleToggle,
369
- "onUpdate:selectMode": (val) => {
370
- selectMode.value = val;
371
- if (!val && !open.value) {
372
- open.value = true;
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;
373
487
  }
374
488
  },
375
- "onUpdate:sessionListCollapsed": (val) => {
376
- sessionListCollapsed.value = val;
377
- },
378
- "onUpdate:theme": (val) => {
379
- theme.value = val;
380
- },
381
- "onToggle-theme": (val) => {
382
- theme.value = val;
383
- },
384
- "onCreate-session": createSession,
385
- "onDelete-session": deleteSession,
386
- "onSelect-session": selectSession,
387
- "onClick-selected-node": handleSelectNode,
388
- "onClear-selected-nodes": handleClearSelected,
389
- "onRemove-selected-node": ({ index }) => {
390
- selectedElements.value.splice(index, 1);
391
- updateContext(true);
392
- },
393
- "onEmpty-action": createSession
394
- });
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
+ );
395
550
  };
396
551
  }
397
552
  };
@@ -400,5 +555,148 @@ if (!window[INIT_MARKER]) {
400
555
  window[INIT_MARKER] = true;
401
556
  const container = document.createElement("div");
402
557
  document.body.appendChild(container);
403
- createApp(App).mount(container);
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;
404
700
  }
701
+ `;
702
+ document.head.appendChild(style);
package/es/core/api.d.ts CHANGED
@@ -11,4 +11,5 @@ export declare class OpenCodeAPI {
11
11
  getToolIds(retries?: number): Promise<string[]>;
12
12
  warmupChromeMcp(viteOrigin?: string): Promise<void>;
13
13
  getOrCreateSession(): Promise<string>;
14
+ retryWarmupChromeMcp(viteOrigin?: string): Promise<boolean>;
14
15
  }