vite-plugin-opencode-assistant 1.0.44 → 1.0.48

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/core/api.js CHANGED
@@ -59,21 +59,6 @@ class OpenCodeAPI {
59
59
  __publicField(this, "getPort", getPort);
60
60
  __publicField(this, "getProxyPort", getProxyPort);
61
61
  __publicField(this, "warmupChromeMcpConfig", warmupChromeMcpConfig);
62
- __publicField(this, "failedFreeModels", /* @__PURE__ */ new Set());
63
- }
64
- markModelAsFailed(providerID, modelID) {
65
- const key = `${providerID}:${modelID}`;
66
- this.failedFreeModels.add(key);
67
- log.debug("Marked model as failed", {
68
- providerID,
69
- modelID,
70
- key,
71
- failedCount: this.failedFreeModels.size
72
- });
73
- }
74
- clearFailedModels() {
75
- this.failedFreeModels.clear();
76
- log.debug("Cleared failed models cache");
77
62
  }
78
63
  createHttpRequest(options, body, timeout) {
79
64
  const timer = new PerformanceTimer("HTTP Request", {
@@ -187,7 +172,7 @@ class OpenCodeAPI {
187
172
  throw lastError;
188
173
  });
189
174
  }
190
- getCheapestModel() {
175
+ getAvailableModels() {
191
176
  return __async(this, null, function* () {
192
177
  var _a, _b;
193
178
  try {
@@ -200,7 +185,6 @@ class OpenCodeAPI {
200
185
  const connectedProviders = new Set(response.connected);
201
186
  const allModels = [];
202
187
  for (const provider of response.all) {
203
- if (provider.id === "opencode") continue;
204
188
  if (!connectedProviders.has(provider.id)) {
205
189
  log.debug("Skipping not connected provider", { providerID: provider.id });
206
190
  continue;
@@ -216,34 +200,14 @@ class OpenCodeAPI {
216
200
  }
217
201
  }
218
202
  allModels.sort((a, b) => a.inputCost - b.inputCost);
219
- const availableModel = allModels.find(
220
- (model) => !this.failedFreeModels.has(`${model.providerID}:${model.modelID}`)
221
- );
222
- if (!availableModel) {
223
- log.debug("All models have failed", {
224
- totalModels: allModels.length,
225
- failedModels: this.failedFreeModels.size,
226
- connectedProviders: response.connected
227
- });
228
- return null;
229
- }
230
- log.debug("Found cheapest available model for warmup", {
231
- providerID: availableModel.providerID,
232
- modelID: availableModel.modelID,
233
- name: availableModel.name,
234
- inputCost: availableModel.inputCost,
235
- releaseDate: availableModel.releaseDate,
236
- totalModels: allModels.length,
237
- failedModels: this.failedFreeModels.size,
203
+ log.debug("Found available models for warmup", {
204
+ count: allModels.length,
238
205
  connectedProviders: response.connected
239
206
  });
240
- return {
241
- providerID: availableModel.providerID,
242
- modelID: availableModel.modelID
243
- };
207
+ return allModels;
244
208
  } catch (error) {
245
- log.warn("Failed to get cheapest model", { error });
246
- return null;
209
+ log.warn("Failed to get available models", { error });
210
+ return [];
247
211
  }
248
212
  });
249
213
  }
@@ -317,12 +281,10 @@ class OpenCodeAPI {
317
281
  throw lastError;
318
282
  });
319
283
  }
320
- warmupChromeMcp(projectDir, viteOrigin) {
284
+ executeWarmupChromeMcp(projectDir, operation, viteOrigin, selectedModel) {
321
285
  return __async(this, null, function* () {
322
- if (!this.warmupChromeMcpConfig) return;
323
- const timer = log.timer("warmupChromeMcp", { viteOrigin });
286
+ const timer = log.timer(`${operation}WarmupChromeMcp`, { viteOrigin, operation });
324
287
  let warmupSessionId = null;
325
- let freeModel = null;
326
288
  const chromeAvailable = yield checkChromeDevToolsAvailable();
327
289
  if (!chromeAvailable) {
328
290
  const error = new ChromeMcpWarmupError(
@@ -330,14 +292,14 @@ class OpenCodeAPI {
330
292
  "Chrome DevTools Protocol is not available",
331
293
  "Chrome remote debugging is not enabled or not running on port 9222. Please enable Chrome remote debugging first."
332
294
  );
333
- log.warn("Chrome DevTools not available", {
295
+ log.warn(`Chrome DevTools not available for ${operation}`, {
334
296
  port: CHROME_DEVTOOLS_PORT,
335
297
  hint: "Enable Chrome remote debugging at chrome://inspect/#remote-debugging"
336
298
  });
337
- timer.end("Chrome DevTools not available");
338
- throw error;
299
+ timer.end(`Chrome DevTools not available for ${operation}`);
300
+ return { success: false, error };
339
301
  }
340
- log.debug("Chrome DevTools is available, proceeding with warmup");
302
+ log.debug(`Chrome DevTools is available, proceeding with ${operation} warmup`);
341
303
  try {
342
304
  const warmupSession = yield this.createSession(
343
305
  projectDir,
@@ -345,14 +307,26 @@ class OpenCodeAPI {
345
307
  "__chrome_mcp_warmup__"
346
308
  );
347
309
  warmupSessionId = warmupSession.id;
348
- freeModel = yield this.getCheapestModel();
349
- if (freeModel) {
350
- log.debug("Using cheapest model for warmup", {
351
- providerID: freeModel.providerID,
352
- modelID: freeModel.modelID
353
- });
310
+ let modelToUse = selectedModel;
311
+ if (!modelToUse) {
312
+ const models = yield this.getAvailableModels();
313
+ if (models.length > 0) {
314
+ modelToUse = {
315
+ providerID: models[0].providerID,
316
+ modelID: models[0].modelID
317
+ };
318
+ log.debug(`Using cheapest model for ${operation} warmup`, {
319
+ providerID: modelToUse.providerID,
320
+ modelID: modelToUse.modelID
321
+ });
322
+ } else {
323
+ log.debug(`No model available for ${operation}, using default model`);
324
+ }
354
325
  } else {
355
- log.debug("No model available, using default model");
326
+ log.debug(`Using selected model for ${operation} warmup`, {
327
+ providerID: modelToUse.providerID,
328
+ modelID: modelToUse.modelID
329
+ });
356
330
  }
357
331
  const WARMUP_TIMEOUT = 6e4;
358
332
  const data = yield this.createHttpRequest(
@@ -370,10 +344,10 @@ class OpenCodeAPI {
370
344
  text: "Test if the chrome-devtools_list_pages tool is available. If available, reply with: ready. If not available, explain why."
371
345
  }
372
346
  ]
373
- }, freeModel && {
347
+ }, modelToUse && {
374
348
  model: {
375
- providerID: freeModel.providerID,
376
- modelID: freeModel.modelID
349
+ providerID: modelToUse.providerID,
350
+ modelID: modelToUse.modelID
377
351
  }
378
352
  })),
379
353
  WARMUP_TIMEOUT
@@ -394,56 +368,43 @@ class OpenCodeAPI {
394
368
  `AI responded with: ${responseText.substring(0, 200)}`
395
369
  );
396
370
  }
397
- timer.end("Chrome MCP warmed up");
371
+ timer.end(`Chrome MCP ${operation} warmed up successfully`);
372
+ return { success: true };
398
373
  } catch (e) {
399
374
  if (e instanceof ChromeMcpWarmupError) {
400
375
  if (e.type === ChromeMcpWarmupErrorType.SESSION_ERROR) {
401
376
  timer.end("Session creation failed");
402
377
  }
403
- log.warn(`Chrome MCP warmup failed: ${e.type}`, __spreadValues({
378
+ log.warn(`Chrome MCP ${operation} warmup failed: ${e.type}`, {
404
379
  message: e.message,
405
380
  details: e.details
406
- }, freeModel && {
407
- model: `${freeModel.providerID}/${freeModel.modelID}`
408
- }));
409
- timer.end(`Chrome MCP warmup failed: ${e.type}`);
410
- throw e;
411
- }
412
- if (freeModel) {
413
- this.markModelAsFailed(freeModel.providerID, freeModel.modelID);
414
- log.debug("Marked model as failed due to warmup error", {
415
- providerID: freeModel.providerID,
416
- modelID: freeModel.modelID,
417
- error: e instanceof Error ? e.message : String(e)
418
381
  });
382
+ timer.end(`Chrome MCP ${operation} warmup failed: ${e.type}`);
383
+ return { success: false, error: e };
419
384
  }
420
385
  const errorMessage = e instanceof Error ? e.message : String(e);
421
386
  if (errorMessage.includes("timeout") || errorMessage.includes("Timeout")) {
422
387
  const error2 = new ChromeMcpWarmupError(
423
388
  ChromeMcpWarmupErrorType.AI_TIMEOUT,
424
389
  "AI response timeout",
425
- "AI did not respond within 30 seconds. Please check if the OpenCode AI model is properly configured and available."
390
+ "AI did not respond within 60 seconds. Please check if the OpenCode AI model is properly configured and available."
426
391
  );
427
- log.warn("Chrome MCP warmup timeout", __spreadValues({
392
+ log.warn(`Chrome MCP ${operation} warmup timeout`, {
428
393
  error: errorMessage
429
- }, freeModel && {
430
- model: `${freeModel.providerID}/${freeModel.modelID}`
431
- }));
432
- timer.end("Chrome MCP warmup timeout");
433
- throw error2;
394
+ });
395
+ timer.end(`Chrome MCP ${operation} warmup timeout`);
396
+ return { success: false, error: error2 };
434
397
  }
435
398
  const error = new ChromeMcpWarmupError(
436
399
  ChromeMcpWarmupErrorType.UNKNOWN,
437
- "Unknown error during Chrome MCP warmup",
400
+ `Unknown error during Chrome MCP ${operation} warmup`,
438
401
  errorMessage
439
402
  );
440
- log.warn("Chrome MCP warmup failed with unknown error", __spreadValues({
403
+ log.warn(`Chrome MCP ${operation} warmup failed with unknown error`, {
441
404
  error: errorMessage
442
- }, freeModel && {
443
- model: `${freeModel.providerID}/${freeModel.modelID}`
444
- }));
445
- timer.end("Chrome MCP warmup failed");
446
- throw error;
405
+ });
406
+ timer.end(`Chrome MCP ${operation} warmup failed`);
407
+ return { success: false, error };
447
408
  } finally {
448
409
  if (warmupSessionId) {
449
410
  try {
@@ -458,6 +419,27 @@ class OpenCodeAPI {
458
419
  }
459
420
  });
460
421
  }
422
+ warmupChromeMcp(projectDir, viteOrigin) {
423
+ return __async(this, null, function* () {
424
+ if (!this.warmupChromeMcpConfig) return;
425
+ const models = yield this.getAvailableModels();
426
+ const cheapestModel = models[0];
427
+ const result = yield this.executeWarmupChromeMcp(
428
+ projectDir,
429
+ "warmup",
430
+ viteOrigin,
431
+ cheapestModel ? { providerID: cheapestModel.providerID, modelID: cheapestModel.modelID } : void 0
432
+ );
433
+ if (!result.success) {
434
+ throw result.error;
435
+ }
436
+ });
437
+ }
438
+ retryWarmupChromeMcp(projectDir, viteOrigin, selectedModel) {
439
+ return __async(this, null, function* () {
440
+ return this.executeWarmupChromeMcp(projectDir, "retry", viteOrigin, selectedModel);
441
+ });
442
+ }
461
443
  getOrCreateSession(projectDir) {
462
444
  return __async(this, null, function* () {
463
445
  const timer = log.timer("getOrCreateSession", { projectDir });
@@ -479,148 +461,6 @@ class OpenCodeAPI {
479
461
  return url;
480
462
  });
481
463
  }
482
- retryWarmupChromeMcp(projectDir, viteOrigin) {
483
- return __async(this, null, function* () {
484
- const timer = log.timer("retryWarmupChromeMcp", { viteOrigin });
485
- let warmupSessionId = null;
486
- let freeModel = null;
487
- const chromeAvailable = yield checkChromeDevToolsAvailable();
488
- if (!chromeAvailable) {
489
- const error = new ChromeMcpWarmupError(
490
- ChromeMcpWarmupErrorType.CHROME_NOT_CONNECTED,
491
- "Chrome DevTools Protocol is not available",
492
- "Chrome remote debugging is not enabled or not running on port 9222. Please enable Chrome remote debugging first."
493
- );
494
- log.warn("Chrome DevTools not available for retry", {
495
- port: CHROME_DEVTOOLS_PORT,
496
- hint: "Enable Chrome remote debugging at chrome://inspect/#remote-debugging"
497
- });
498
- timer.end("Chrome DevTools not available for retry");
499
- return { success: false, error };
500
- }
501
- log.debug("Chrome DevTools is available, proceeding with retry warmup");
502
- try {
503
- const warmupSession = yield this.createSession(
504
- projectDir,
505
- DEFAULT_RETRIES,
506
- "__chrome_mcp_warmup__"
507
- );
508
- warmupSessionId = warmupSession.id;
509
- freeModel = yield this.getCheapestModel();
510
- if (freeModel) {
511
- log.debug("Using cheapest model for retry warmup", {
512
- providerID: freeModel.providerID,
513
- modelID: freeModel.modelID
514
- });
515
- } else {
516
- log.debug("No model available for retry, using default model");
517
- }
518
- const WARMUP_TIMEOUT = 6e4;
519
- const data = yield this.createHttpRequest(
520
- {
521
- hostname: this.hostname,
522
- port: this.getPort(),
523
- path: `/session/${warmupSessionId}/message`,
524
- method: "POST",
525
- headers: { "Content-Type": "application/json" }
526
- },
527
- JSON.stringify(__spreadValues({
528
- parts: [
529
- {
530
- type: "text",
531
- text: "Test if the chrome-devtools_list_pages tool is available. If available, reply with: ready. If not available, explain why."
532
- }
533
- ]
534
- }, freeModel && {
535
- model: {
536
- providerID: freeModel.providerID,
537
- modelID: freeModel.modelID
538
- }
539
- })),
540
- WARMUP_TIMEOUT
541
- );
542
- log.debug("Chrome MCP warmup response:", { data });
543
- const responseText = extractTextFromResponse(data);
544
- if (!responseText) {
545
- throw new ChromeMcpWarmupError(
546
- ChromeMcpWarmupErrorType.AI_RESPONSE_ERROR,
547
- "AI did not respond to the warmup request",
548
- "Empty response from AI"
549
- );
550
- }
551
- const lowerResponse = responseText.toLowerCase();
552
- if (!lowerResponse.includes("ready")) {
553
- throw new ChromeMcpWarmupError(
554
- ChromeMcpWarmupErrorType.AI_RESPONSE_ERROR,
555
- "AI response does not indicate success",
556
- `AI responded with: ${responseText.substring(0, 200)}`
557
- );
558
- }
559
- timer.end("Chrome MCP warmed up successfully");
560
- return { success: true };
561
- } catch (e) {
562
- if (e instanceof ChromeMcpWarmupError) {
563
- if (e.type === ChromeMcpWarmupErrorType.SESSION_ERROR) {
564
- timer.end("Session creation failed");
565
- }
566
- log.warn(`Chrome MCP warmup retry failed: ${e.type}`, __spreadValues({
567
- message: e.message,
568
- details: e.details
569
- }, freeModel && {
570
- model: `${freeModel.providerID}/${freeModel.modelID}`
571
- }));
572
- timer.end(`Chrome MCP warmup retry failed: ${e.type}`);
573
- return { success: false, error: e };
574
- }
575
- if (freeModel) {
576
- this.markModelAsFailed(freeModel.providerID, freeModel.modelID);
577
- log.debug("Marked model as failed due to retry warmup error", {
578
- providerID: freeModel.providerID,
579
- modelID: freeModel.modelID,
580
- error: e instanceof Error ? e.message : String(e)
581
- });
582
- }
583
- const errorMessage = e instanceof Error ? e.message : String(e);
584
- if (errorMessage.includes("timeout") || errorMessage.includes("Timeout")) {
585
- const error2 = new ChromeMcpWarmupError(
586
- ChromeMcpWarmupErrorType.AI_TIMEOUT,
587
- "AI response timeout",
588
- "AI did not respond within 60 seconds. Please check if the OpenCode AI model is properly configured and available."
589
- );
590
- log.warn("Chrome MCP warmup retry timeout", __spreadValues({
591
- error: errorMessage
592
- }, freeModel && {
593
- model: `${freeModel.providerID}/${freeModel.modelID}`
594
- }));
595
- timer.end("Chrome MCP warmup retry timeout");
596
- return { success: false, error: error2 };
597
- }
598
- const error = new ChromeMcpWarmupError(
599
- ChromeMcpWarmupErrorType.UNKNOWN,
600
- "Unknown error during Chrome MCP warmup retry",
601
- errorMessage
602
- );
603
- log.warn("Chrome MCP warmup retry failed with unknown error", __spreadValues({
604
- error: errorMessage
605
- }, freeModel && {
606
- model: `${freeModel.providerID}/${freeModel.modelID}`
607
- }));
608
- timer.end("Chrome MCP warmup retry failed");
609
- return { success: false, error };
610
- } finally {
611
- if (warmupSessionId) {
612
- try {
613
- yield this.deleteSession(warmupSessionId, 5);
614
- } catch (e) {
615
- log.warn("Failed to delete warmup session after retries", {
616
- error: e,
617
- warmupSessionId
618
- });
619
- }
620
- }
621
- }
622
- });
623
- }
624
464
  }
625
465
  export {
626
466
  OpenCodeAPI
@@ -1,5 +1,6 @@
1
1
  import type { ResultPromise } from "execa";
2
2
  import type http from "http";
3
+ import type { ModelInfo } from "@vite-plugin-opencode-assistant/shared";
3
4
  import type { OpenCodeOptions, ServiceStartupTask } from "@vite-plugin-opencode-assistant/shared";
4
5
  import { ChromeMcpWarmupErrorType } from "@vite-plugin-opencode-assistant/shared";
5
6
  import type { OpenCodeAPI } from "./api.js";
@@ -26,7 +27,11 @@ export declare class OpenCodeService {
26
27
  constructor(config: Required<OpenCodeOptions>, api: OpenCodeAPI, sseClients: Set<http.ServerResponse>, onPortAllocated: (port: number) => void, onProxyPortAllocated: (port: number) => void);
27
28
  private sendTaskUpdate;
28
29
  start(corsOrigins?: string[], contextApiUrl?: string, logsApiUrl?: string, viteOrigin?: string): Promise<void>;
29
- retryWarmupChromeMcp(viteOrigin?: string): Promise<{
30
+ getAvailableModels(): Promise<ModelInfo[]>;
31
+ retryWarmupChromeMcp(viteOrigin?: string, selectedModel?: {
32
+ providerID: string;
33
+ modelID: string;
34
+ }): Promise<{
30
35
  success: boolean;
31
36
  errorType?: string;
32
37
  errorMessage?: string;
@@ -262,9 +262,18 @@ Please install OpenCode first:
262
262
  return this.startPromise;
263
263
  });
264
264
  }
265
- retryWarmupChromeMcp(viteOrigin) {
265
+ getAvailableModels() {
266
266
  return __async(this, null, function* () {
267
- const result = yield this.api.retryWarmupChromeMcp(this.workspaceRoot, viteOrigin);
267
+ return this.api.getAvailableModels();
268
+ });
269
+ }
270
+ retryWarmupChromeMcp(viteOrigin, selectedModel) {
271
+ return __async(this, null, function* () {
272
+ const result = yield this.api.retryWarmupChromeMcp(
273
+ this.workspaceRoot,
274
+ viteOrigin,
275
+ selectedModel
276
+ );
268
277
  if (result.success) {
269
278
  this.chromeMcpWarmupFailed = false;
270
279
  this.sendTaskUpdate("ready");
@@ -1,4 +1,4 @@
1
- import type { PageContext, SessionInfo, ServiceStartupTask } from "@vite-plugin-opencode-assistant/shared";
1
+ import type { PageContext, SessionInfo, ServiceStartupTask, ModelInfo } from "@vite-plugin-opencode-assistant/shared";
2
2
  import type http from "http";
3
3
  export interface EndpointContext {
4
4
  get webUrl(): string | null;
@@ -15,7 +15,11 @@ export interface EndpointContext {
15
15
  deleteSession: (id: string) => Promise<void>;
16
16
  resolveWidgetPath: () => string;
17
17
  resolveWidgetStylePath: () => string;
18
- retryWarmupChromeMcp: () => Promise<{
18
+ getAvailableModels: () => Promise<ModelInfo[]>;
19
+ retryWarmupChromeMcp: (selectedModel?: {
20
+ providerID: string;
21
+ modelID: string;
22
+ }) => Promise<{
19
23
  success: boolean;
20
24
  errorType?: string;
21
25
  errorMessage?: string;
@@ -1,3 +1,4 @@
1
+ var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
1
2
  var __async = (__this, __arguments, generator) => {
2
3
  return new Promise((resolve, reject) => {
3
4
  var fulfilled = (value) => {
@@ -18,37 +19,83 @@ var __async = (__this, __arguments, generator) => {
18
19
  step((generator = generator.apply(__this, __arguments)).next());
19
20
  });
20
21
  };
22
+ var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
21
23
  import { createLogger } from "@vite-plugin-opencode-assistant/shared";
22
24
  const log = createLogger("Endpoints:Warmup");
23
25
  function setupWarmupEndpoint(server, ctx) {
24
26
  server.middlewares.use("/__opencode_warmup__", (req, res) => __async(null, null, function* () {
27
+ if (req.method === "GET") {
28
+ try {
29
+ const models = yield ctx.getAvailableModels();
30
+ res.setHeader("Content-Type", "application/json");
31
+ res.writeHead(200);
32
+ res.end(JSON.stringify({ success: true, models }));
33
+ } catch (e) {
34
+ log.error("Failed to get available models", { error: e });
35
+ res.setHeader("Content-Type", "application/json");
36
+ res.writeHead(500);
37
+ res.end(JSON.stringify({ success: false, models: [] }));
38
+ }
39
+ return;
40
+ }
25
41
  if (req.method !== "POST") {
26
42
  res.writeHead(405);
27
43
  res.end("Method not allowed");
28
44
  return;
29
45
  }
30
46
  try {
31
- const result = yield ctx.retryWarmupChromeMcp();
47
+ let body = "";
48
+ try {
49
+ for (var iter = __forAwait(req), more, temp, error; more = !(temp = yield iter.next()).done; more = false) {
50
+ const chunk = temp.value;
51
+ body += chunk;
52
+ }
53
+ } catch (temp) {
54
+ error = [temp];
55
+ } finally {
56
+ try {
57
+ more && (temp = iter.return) && (yield temp.call(iter));
58
+ } finally {
59
+ if (error)
60
+ throw error[0];
61
+ }
62
+ }
63
+ let selectedModel;
64
+ if (body) {
65
+ try {
66
+ const parsed = JSON.parse(body);
67
+ if (parsed.providerID && parsed.modelID) {
68
+ selectedModel = { providerID: parsed.providerID, modelID: parsed.modelID };
69
+ }
70
+ } catch (e) {
71
+ log.debug("Failed to parse request body, using default model");
72
+ }
73
+ }
74
+ const result = yield ctx.retryWarmupChromeMcp(selectedModel);
32
75
  res.setHeader("Content-Type", "application/json");
33
76
  res.writeHead(200);
34
77
  if (result.success) {
35
78
  res.end(JSON.stringify({ success: true }));
36
79
  } else {
37
- res.end(JSON.stringify({
38
- success: false,
39
- errorType: result.errorType,
40
- error: result.errorMessage
41
- }));
80
+ res.end(
81
+ JSON.stringify({
82
+ success: false,
83
+ errorType: result.errorType,
84
+ error: result.errorMessage
85
+ })
86
+ );
42
87
  }
43
88
  } catch (e) {
44
89
  log.error("Failed to retry warmup", { error: e });
45
90
  res.setHeader("Content-Type", "application/json");
46
91
  res.writeHead(500);
47
- res.end(JSON.stringify({
48
- success: false,
49
- errorType: "UNKNOWN",
50
- error: String(e)
51
- }));
92
+ res.end(
93
+ JSON.stringify({
94
+ success: false,
95
+ errorType: "UNKNOWN",
96
+ error: String(e)
97
+ })
98
+ );
52
99
  }
53
100
  }));
54
101
  }
package/es/index.js CHANGED
@@ -123,7 +123,8 @@ function createOpenCodePlugin(options = {}) {
123
123
  deleteSession: (id) => api.deleteSession(id),
124
124
  resolveWidgetPath,
125
125
  resolveWidgetStylePath,
126
- retryWarmupChromeMcp: () => service.retryWarmupChromeMcp(getViteOrigin())
126
+ getAvailableModels: () => service.getAvailableModels(),
127
+ retryWarmupChromeMcp: (selectedModel) => service.retryWarmupChromeMcp(getViteOrigin(), selectedModel)
127
128
  });
128
129
  (_a2 = server.httpServer) == null ? void 0 : _a2.on("listening", () => __async(null, null, function* () {
129
130
  var _a3;
@@ -96,6 +96,7 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
96
96
  const loading = (0, import_vue2.ref)(false);
97
97
  const widgetRef = (0, import_vue2.ref)(null);
98
98
  const retryingWarmup = (0, import_vue2.ref)(false);
99
+ const availableModels = (0, import_vue2.ref)([]);
99
100
  const {
100
101
  theme: initialTheme = "auto",
101
102
  open: autoOpen = false,
@@ -175,10 +176,14 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
175
176
  }
176
177
  return "\u52A0\u8F7D\u4F1A\u8BDD...";
177
178
  });
178
- const retryWarmup = () => __async(null, null, function* () {
179
+ const retryWarmup = (selectedModel) => __async(null, null, function* () {
179
180
  retryingWarmup.value = true;
180
181
  try {
181
- const res = yield fetch("/__opencode_warmup__", { method: "POST" });
182
+ const res = yield fetch("/__opencode_warmup__", {
183
+ method: "POST",
184
+ headers: { "Content-Type": "application/json" },
185
+ body: selectedModel ? JSON.stringify(selectedModel) : ""
186
+ });
182
187
  const data = yield res.json();
183
188
  if (data.success) {
184
189
  chromeMcpFailed.value = false;
@@ -206,6 +211,18 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
206
211
  retryingWarmup.value = false;
207
212
  }
208
213
  });
214
+ const fetchAvailableModels = () => __async(null, null, function* () {
215
+ try {
216
+ const res = yield fetch("/__opencode_warmup__", { method: "GET" });
217
+ const data = yield res.json();
218
+ if (data.success && data.models) {
219
+ availableModels.value = data.models;
220
+ }
221
+ } catch (e) {
222
+ console.error("[OpenCode] Failed to fetch available models:", e);
223
+ availableModels.value = [];
224
+ }
225
+ });
209
226
  const ensureServicesStarted = () => __async(null, null, function* () {
210
227
  if (serviceStatus.value !== "idle") return true;
211
228
  try {
@@ -245,6 +262,11 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
245
262
  loadSessions();
246
263
  }
247
264
  });
265
+ (0, import_vue2.watch)(chromeMcpFailed, (failed) => {
266
+ if (failed) {
267
+ fetchAvailableModels();
268
+ }
269
+ });
248
270
  (0, import_vue2.onMounted)(() => {
249
271
  if (serviceStatus.value === "ready") {
250
272
  loadSessions();
@@ -332,7 +354,7 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
332
354
  const handleFrameLoaded = () => {
333
355
  iframeLoading.value = false;
334
356
  };
335
- const __returned__ = { props, open, selectMode, sessionListCollapsed, loading, widgetRef, retryingWarmup, initialTheme, autoOpen, hotkey, proxyPort, proxyHost, displayMode, splitMode, widgetTheme, splitPanelWidth, proxyBaseUrl, showNotification, serviceStatus, chromeMcpFailed, chromeMcpErrorType, chromeMcpErrorMessage, loadingText, updateStatusFromTask, setStarting, selectedElements, removeElement, clearElements, theme, sendThemeToIframe, sessions, loadingSessionList, currentSessionId, iframeSrc, iframeLoading, loadSessions, createSession, deleteSession, selectSession, updateSessionInfo, updateContext, serverSSE, opencodeSSE, thinking, sessionStates, showSessionListSkeleton, computedLoading, displayLoadingText, retryWarmup, ensureServicesStarted, toggleSelectMode, handleToggle, handleSelectNode, handleClearSelected, handleSelectModeChange, handleSessionListCollapsedChange, handleThemeChange, handleSplitPanelWidthChange, handleRemoveSelectedNode, handleFrameLoaded, get OpenCodeWidget() {
357
+ const __returned__ = { props, open, selectMode, sessionListCollapsed, loading, widgetRef, retryingWarmup, availableModels, initialTheme, autoOpen, hotkey, proxyPort, proxyHost, displayMode, splitMode, widgetTheme, splitPanelWidth, proxyBaseUrl, showNotification, serviceStatus, chromeMcpFailed, chromeMcpErrorType, chromeMcpErrorMessage, loadingText, updateStatusFromTask, setStarting, selectedElements, removeElement, clearElements, theme, sendThemeToIframe, sessions, loadingSessionList, currentSessionId, iframeSrc, iframeLoading, loadSessions, createSession, deleteSession, selectSession, updateSessionInfo, updateContext, serverSSE, opencodeSSE, thinking, sessionStates, showSessionListSkeleton, computedLoading, displayLoadingText, retryWarmup, fetchAvailableModels, ensureServicesStarted, toggleSelectMode, handleToggle, handleSelectNode, handleClearSelected, handleSelectModeChange, handleSessionListCollapsedChange, handleThemeChange, handleSplitPanelWidthChange, handleRemoveSelectedNode, handleFrameLoaded, get OpenCodeWidget() {
336
358
  return import_components.OpenCodeWidget;
337
359
  }, LoadingContent: import_LoadingContent_vue.default, ChromeWarmupError: import_ChromeWarmupError_vue.default };
338
360
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
@@ -384,8 +406,9 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
384
406
  retrying: $setup.retryingWarmup,
385
407
  "error-type": $setup.chromeMcpErrorType,
386
408
  "error-message": $setup.chromeMcpErrorMessage,
409
+ models: $setup.availableModels,
387
410
  onRetry: $setup.retryWarmup
388
- }, null, 8, ["retrying", "error-type", "error-message"])) : (0, import_vue3.createCommentVNode)("v-if", true)
411
+ }, null, 8, ["retrying", "error-type", "error-message", "models"])) : (0, import_vue3.createCommentVNode)("v-if", true)
389
412
  ]),
390
413
  _: 1
391
414
  /* STABLE */
@@ -1 +1 @@
1
- .opencode-chrome-warmup-error-details[data-v-13778a4c]{margin-top:8px;padding:12px;background:var(--oc-bg-tertiary);border-radius:6px;font-family:Monaco,Menlo,Ubuntu Mono,monospace;font-size:12px;color:var(--oc-text-secondary);max-height:120px;overflow-y:auto;word-break:break-word}
1
+ .opencode-chrome-warmup-error-details[data-v-06c8b833]{margin-top:8px;padding:12px;background:var(--oc-bg-tertiary);border-radius:6px;font-family:Monaco,Menlo,Ubuntu Mono,monospace;font-size:12px;color:var(--oc-text-secondary);max-height:120px;overflow-y:auto;word-break:break-word}.opencode-model-selector[data-v-06c8b833]{display:flex;flex-direction:column;gap:12px;max-width:400px}.select-wrapper[data-v-06c8b833]{position:relative;width:100%}.native-select[data-v-06c8b833]{width:100%;padding:10px 36px 10px 12px;border-radius:8px;border:1px solid var(--oc-border-primary);background:var(--oc-bg-primary);color:var(--oc-text-primary);font-size:14px;cursor:pointer;outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;transition:border-color .15s ease,background-color .15s ease,box-shadow .15s ease}.native-select[data-v-06c8b833]:hover:not(:disabled){border-color:var(--oc-border-hover);background:var(--oc-bg-secondary)}.native-select[data-v-06c8b833]:focus{border-color:var(--oc-primary);box-shadow:0 0 0 2px rgba(var(--oc-primary-rgb, 59, 130, 246),.2)}.native-select[data-v-06c8b833]:disabled{opacity:.6;cursor:not-allowed}.native-select option[data-v-06c8b833]{background:var(--oc-bg-primary);color:var(--oc-text-primary);padding:8px}.native-select optgroup[data-v-06c8b833]{color:var(--oc-text-secondary);font-weight:600;font-size:12px}.select-arrow[data-v-06c8b833]{position:absolute;right:12px;top:50%;transform:translateY(-50%);pointer-events:none;color:var(--oc-text-secondary);display:flex;align-items:center}.native-select:disabled+.select-arrow[data-v-06c8b833]{opacity:.6}.retry-btn[data-v-06c8b833]{width:100%;padding:10px 20px;border-radius:8px;border:none;background:var(--oc-primary);color:#fff;font-size:14px;cursor:pointer;transition:background-color .15s ease}.retry-btn[data-v-06c8b833]:hover:not(:disabled){background:var(--oc-primary-hover)}.retry-btn[data-v-06c8b833]:disabled{opacity:.6;cursor:not-allowed}.opencode-chrome-warmup-failed-actions[data-v-06c8b833]{margin-top:16px;display:flex;justify-content:center}.opencode-chrome-warmup-failed-btn[data-v-06c8b833]{padding:10px 20px;border-radius:8px;border:none;font-size:14px;cursor:pointer;transition:background-color .15s ease}.opencode-chrome-warmup-failed-btn.primary[data-v-06c8b833]{background:var(--oc-primary);color:#fff}.opencode-chrome-warmup-failed-btn.primary[data-v-06c8b833]:hover:not(:disabled){background:var(--oc-primary-hover)}.opencode-chrome-warmup-failed-btn[data-v-06c8b833]:disabled{opacity:.6;cursor:not-allowed}