vite-plugin-opencode-assistant 1.0.15 → 1.0.17
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/App.vue.d.ts +6 -0
- package/es/client/App.vue.js +317 -0
- package/es/client/components/ChromeWarmupError-sfc.css +1 -0
- package/es/client/components/ChromeWarmupError.vue.d.ts +11 -0
- package/es/client/components/ChromeWarmupError.vue.js +196 -0
- package/es/client/components/LoadingContent.vue.d.ts +5 -0
- package/es/client/components/LoadingContent.vue.js +39 -0
- package/es/client/composables/useContext.d.ts +8 -0
- package/es/client/composables/useContext.js +63 -0
- package/es/client/composables/useHotkey.d.ts +12 -0
- package/es/client/composables/useHotkey.js +41 -0
- package/es/client/composables/useSSE.d.ts +20 -0
- package/es/client/composables/useSSE.js +61 -0
- package/es/client/composables/useSelectedElements.d.ts +19 -0
- package/es/client/composables/useSelectedElements.js +43 -0
- package/es/client/composables/useServiceStatus.d.ts +13 -0
- package/es/client/composables/useServiceStatus.js +53 -0
- package/es/client/composables/useSessions.d.ts +26 -0
- package/es/client/composables/useSessions.js +127 -0
- package/es/client/composables/useTheme.d.ts +12 -0
- package/es/client/composables/useTheme.js +42 -0
- package/es/client/index.d.ts +1 -1
- package/es/client/index.js +5 -675
- package/es/client/styles.css +1 -0
- package/es/core/api.d.ts +18 -6
- package/es/core/api.js +345 -89
- package/es/core/proxy-server.js +266 -2
- package/es/core/service.d.ts +9 -2
- package/es/core/service.js +35 -31
- package/es/endpoints/index.js +1 -1
- package/es/endpoints/sse.js +0 -3
- package/es/endpoints/start.d.ts +1 -2
- package/es/endpoints/start.js +2 -2
- package/es/endpoints/types.d.ts +5 -2
- package/es/endpoints/warmup.js +15 -3
- package/es/index.js +8 -12
- package/es/utils/system.d.ts +1 -0
- package/es/utils/system.js +28 -0
- package/lib/client/App.vue.d.ts +6 -0
- package/lib/client/App.vue.js +344 -0
- package/lib/client/components/ChromeWarmupError-sfc.css +1 -0
- package/lib/client/components/ChromeWarmupError.vue.d.ts +11 -0
- package/lib/client/components/ChromeWarmupError.vue.js +215 -0
- package/lib/client/components/LoadingContent.vue.d.ts +5 -0
- package/lib/client/components/LoadingContent.vue.js +58 -0
- package/lib/client/composables/useContext.d.ts +8 -0
- package/lib/client/composables/useContext.js +86 -0
- package/lib/client/composables/useHotkey.d.ts +12 -0
- package/lib/client/composables/useHotkey.js +66 -0
- package/lib/client/composables/useSSE.d.ts +20 -0
- package/lib/client/composables/useSSE.js +84 -0
- package/lib/client/composables/useSelectedElements.d.ts +19 -0
- package/lib/client/composables/useSelectedElements.js +66 -0
- package/lib/client/composables/useServiceStatus.d.ts +13 -0
- package/lib/client/composables/useServiceStatus.js +76 -0
- package/lib/client/composables/useSessions.d.ts +26 -0
- package/lib/client/composables/useSessions.js +148 -0
- package/lib/client/composables/useTheme.d.ts +12 -0
- package/lib/client/composables/useTheme.js +65 -0
- package/lib/client/index.d.ts +1 -1
- package/lib/client/index.js +22 -667
- package/lib/client/styles.css +1 -0
- package/lib/client.js +3280 -3109
- package/lib/core/api.d.ts +18 -6
- package/lib/core/api.js +342 -94
- package/lib/core/proxy-server.js +266 -2
- package/lib/core/service.d.ts +9 -2
- package/lib/core/service.js +31 -30
- package/lib/endpoints/index.js +1 -1
- package/lib/endpoints/sse.js +0 -3
- package/lib/endpoints/start.d.ts +1 -2
- package/lib/endpoints/start.js +2 -2
- package/lib/endpoints/types.d.ts +5 -2
- package/lib/endpoints/warmup.js +15 -3
- package/lib/index.js +8 -12
- package/lib/style.css +1 -1
- package/lib/utils/system.d.ts +1 -0
- package/lib/utils/system.js +29 -0
- package/package.json +4 -4
package/es/core/api.d.ts
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import type { SessionInfo } from "@vite-plugin-opencode-assistant/shared";
|
|
2
|
+
import { ChromeMcpWarmupError } from "@vite-plugin-opencode-assistant/shared";
|
|
2
3
|
export declare class OpenCodeAPI {
|
|
3
4
|
private hostname;
|
|
4
5
|
private getPort;
|
|
6
|
+
private getProxyPort;
|
|
5
7
|
private warmupChromeMcpConfig;
|
|
6
|
-
|
|
8
|
+
private failedFreeModels;
|
|
9
|
+
constructor(hostname: string, getPort: () => number, getProxyPort: () => number, warmupChromeMcpConfig?: boolean);
|
|
10
|
+
markModelAsFailed(providerID: string, modelID: string): void;
|
|
11
|
+
clearFailedModels(): void;
|
|
7
12
|
private createHttpRequest;
|
|
8
|
-
getSessions(retries?: number): Promise<SessionInfo[]>;
|
|
9
|
-
createSession(retries?: number, title?: string): Promise<SessionInfo>;
|
|
13
|
+
getSessions(projectDir: string, retries?: number): Promise<SessionInfo[]>;
|
|
14
|
+
createSession(projectDir: string, retries?: number, title?: string): Promise<SessionInfo>;
|
|
15
|
+
getCheapestModel(): Promise<{
|
|
16
|
+
providerID: string;
|
|
17
|
+
modelID: string;
|
|
18
|
+
} | null>;
|
|
10
19
|
deleteSession(sessionId: string, retries?: number): Promise<void>;
|
|
11
20
|
getToolIds(retries?: number): Promise<string[]>;
|
|
12
|
-
warmupChromeMcp(viteOrigin?: string): Promise<void>;
|
|
13
|
-
getOrCreateSession(): Promise<string>;
|
|
14
|
-
retryWarmupChromeMcp(viteOrigin?: string): Promise<
|
|
21
|
+
warmupChromeMcp(projectDir: string, viteOrigin?: string): Promise<void>;
|
|
22
|
+
getOrCreateSession(projectDir: string): Promise<string>;
|
|
23
|
+
retryWarmupChromeMcp(projectDir: string, viteOrigin?: string): Promise<{
|
|
24
|
+
success: boolean;
|
|
25
|
+
error?: ChromeMcpWarmupError;
|
|
26
|
+
}>;
|
|
15
27
|
}
|
package/es/core/api.js
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
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;
|
|
2
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));
|
|
3
20
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
21
|
var __async = (__this, __arguments, generator) => {
|
|
5
22
|
return new Promise((resolve, reject) => {
|
|
@@ -26,43 +43,37 @@ import {
|
|
|
26
43
|
PerformanceTimer,
|
|
27
44
|
createLogger,
|
|
28
45
|
DEFAULT_RETRIES,
|
|
29
|
-
RETRY_DELAY
|
|
46
|
+
RETRY_DELAY,
|
|
47
|
+
ChromeMcpWarmupErrorType,
|
|
48
|
+
ChromeMcpWarmupError,
|
|
49
|
+
CHROME_DEVTOOLS_PORT,
|
|
50
|
+
checkChromeDevToolsAvailable,
|
|
51
|
+
sleep,
|
|
52
|
+
base64Encode,
|
|
53
|
+
extractTextFromResponse
|
|
30
54
|
} from "@vite-plugin-opencode-assistant/shared";
|
|
31
55
|
const log = createLogger("API");
|
|
32
|
-
function sleep(ms) {
|
|
33
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
34
|
-
}
|
|
35
|
-
function base64Encode(str) {
|
|
36
|
-
return Buffer.from(str).toString("base64");
|
|
37
|
-
}
|
|
38
|
-
function extractTextFromResponse(data) {
|
|
39
|
-
if (!data || typeof data !== "object") return null;
|
|
40
|
-
const obj = data;
|
|
41
|
-
if (obj.parts && Array.isArray(obj.parts)) {
|
|
42
|
-
const textParts = obj.parts.filter(
|
|
43
|
-
(p) => p && typeof p === "object" && p.type === "text"
|
|
44
|
-
).map((p) => p.text).filter(Boolean);
|
|
45
|
-
if (textParts.length > 0) return textParts.join("");
|
|
46
|
-
}
|
|
47
|
-
if (obj.text && typeof obj.text === "string") {
|
|
48
|
-
return obj.text;
|
|
49
|
-
}
|
|
50
|
-
if (obj.content && typeof obj.content === "string") {
|
|
51
|
-
return obj.content;
|
|
52
|
-
}
|
|
53
|
-
if (obj.message && typeof obj.message === "string") {
|
|
54
|
-
return obj.message;
|
|
55
|
-
}
|
|
56
|
-
if (typeof data === "string") {
|
|
57
|
-
return data;
|
|
58
|
-
}
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
56
|
class OpenCodeAPI {
|
|
62
|
-
constructor(hostname, getPort, warmupChromeMcpConfig = false) {
|
|
57
|
+
constructor(hostname, getPort, getProxyPort, warmupChromeMcpConfig = false) {
|
|
63
58
|
__publicField(this, "hostname", hostname);
|
|
64
59
|
__publicField(this, "getPort", getPort);
|
|
60
|
+
__publicField(this, "getProxyPort", getProxyPort);
|
|
65
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");
|
|
66
77
|
}
|
|
67
78
|
createHttpRequest(options, body, timeout) {
|
|
68
79
|
const timer = new PerformanceTimer("HTTP Request", {
|
|
@@ -98,20 +109,26 @@ class OpenCodeAPI {
|
|
|
98
109
|
req.end();
|
|
99
110
|
});
|
|
100
111
|
}
|
|
101
|
-
getSessions() {
|
|
102
|
-
return __async(this, arguments, function* (retries = DEFAULT_RETRIES) {
|
|
103
|
-
const timer = log.timer("getSessions", { retries });
|
|
112
|
+
getSessions(_0) {
|
|
113
|
+
return __async(this, arguments, function* (projectDir, retries = DEFAULT_RETRIES) {
|
|
114
|
+
const timer = log.timer("getSessions", { retries, projectDir });
|
|
104
115
|
let lastError = null;
|
|
105
116
|
for (let i = 0; i < retries; i++) {
|
|
106
117
|
try {
|
|
107
|
-
log.debug(`Attempt ${i + 1}/${retries}`, { operation: "getSessions" });
|
|
118
|
+
log.debug(`Attempt ${i + 1}/${retries}`, { operation: "getSessions", projectDir });
|
|
108
119
|
const sessions = yield this.createHttpRequest({
|
|
109
120
|
hostname: this.hostname,
|
|
110
121
|
port: this.getPort(),
|
|
111
|
-
path: "/session"
|
|
122
|
+
path: "/session",
|
|
123
|
+
headers: {
|
|
124
|
+
"x-opencode-directory": encodeURIComponent(projectDir)
|
|
125
|
+
}
|
|
112
126
|
});
|
|
127
|
+
const sessionsWithUrl = sessions.map((s) => __spreadProps(__spreadValues({}, s), {
|
|
128
|
+
url: `http://${this.hostname}:${this.getProxyPort()}/${base64Encode(s.directory)}/session/${s.id}`
|
|
129
|
+
}));
|
|
113
130
|
timer.end(`Found ${sessions.length} sessions`);
|
|
114
|
-
return
|
|
131
|
+
return sessionsWithUrl;
|
|
115
132
|
} catch (e) {
|
|
116
133
|
lastError = e instanceof Error ? e : new Error(String(e));
|
|
117
134
|
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, {
|
|
@@ -129,15 +146,16 @@ class OpenCodeAPI {
|
|
|
129
146
|
throw lastError;
|
|
130
147
|
});
|
|
131
148
|
}
|
|
132
|
-
createSession() {
|
|
133
|
-
return __async(this, arguments, function* (retries = DEFAULT_RETRIES, title) {
|
|
134
|
-
const timer = log.timer("createSession", { retries, title });
|
|
149
|
+
createSession(_0) {
|
|
150
|
+
return __async(this, arguments, function* (projectDir, retries = DEFAULT_RETRIES, title) {
|
|
151
|
+
const timer = log.timer("createSession", { retries, title, projectDir });
|
|
135
152
|
let lastError = null;
|
|
136
153
|
for (let i = 0; i < retries; i++) {
|
|
137
154
|
try {
|
|
138
155
|
log.debug(`Attempt ${i + 1}/${retries}`, {
|
|
139
156
|
operation: "createSession",
|
|
140
|
-
title
|
|
157
|
+
title,
|
|
158
|
+
projectDir
|
|
141
159
|
});
|
|
142
160
|
const requestBody = title ? JSON.stringify({ title }) : void 0;
|
|
143
161
|
const session = yield this.createHttpRequest(
|
|
@@ -146,12 +164,17 @@ class OpenCodeAPI {
|
|
|
146
164
|
port: this.getPort(),
|
|
147
165
|
path: "/session",
|
|
148
166
|
method: "POST",
|
|
149
|
-
headers: requestBody ? { "Content-Type": "application/json" } :
|
|
167
|
+
headers: __spreadProps(__spreadValues({}, requestBody ? { "Content-Type": "application/json" } : {}), {
|
|
168
|
+
"x-opencode-directory": encodeURIComponent(projectDir)
|
|
169
|
+
})
|
|
150
170
|
},
|
|
151
171
|
requestBody
|
|
152
172
|
);
|
|
173
|
+
const sessionWithUrl = __spreadProps(__spreadValues({}, session), {
|
|
174
|
+
url: `http://${this.hostname}:${this.getProxyPort()}/${base64Encode(projectDir)}/session/${session.id}`
|
|
175
|
+
});
|
|
153
176
|
timer.end(`Created session: ${session.id}`);
|
|
154
|
-
return
|
|
177
|
+
return sessionWithUrl;
|
|
155
178
|
} catch (e) {
|
|
156
179
|
lastError = e instanceof Error ? e : new Error(String(e));
|
|
157
180
|
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, {
|
|
@@ -169,6 +192,66 @@ class OpenCodeAPI {
|
|
|
169
192
|
throw lastError;
|
|
170
193
|
});
|
|
171
194
|
}
|
|
195
|
+
getCheapestModel() {
|
|
196
|
+
return __async(this, null, function* () {
|
|
197
|
+
var _a, _b;
|
|
198
|
+
try {
|
|
199
|
+
const response = yield this.createHttpRequest({
|
|
200
|
+
hostname: this.hostname,
|
|
201
|
+
port: this.getPort(),
|
|
202
|
+
path: "/provider",
|
|
203
|
+
method: "GET"
|
|
204
|
+
});
|
|
205
|
+
const connectedProviders = new Set(response.connected);
|
|
206
|
+
const allModels = [];
|
|
207
|
+
for (const provider of response.all) {
|
|
208
|
+
if (provider.id === "opencode") continue;
|
|
209
|
+
if (!connectedProviders.has(provider.id)) {
|
|
210
|
+
log.debug("Skipping not connected provider", { providerID: provider.id });
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
for (const [modelID, model] of Object.entries(provider.models)) {
|
|
214
|
+
allModels.push({
|
|
215
|
+
providerID: provider.id,
|
|
216
|
+
modelID,
|
|
217
|
+
name: model.name,
|
|
218
|
+
inputCost: (_b = (_a = model.cost) == null ? void 0 : _a.input) != null ? _b : 0,
|
|
219
|
+
releaseDate: model.release_date
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
allModels.sort((a, b) => a.inputCost - b.inputCost);
|
|
224
|
+
const availableModel = allModels.find(
|
|
225
|
+
(model) => !this.failedFreeModels.has(`${model.providerID}:${model.modelID}`)
|
|
226
|
+
);
|
|
227
|
+
if (!availableModel) {
|
|
228
|
+
log.debug("All models have failed", {
|
|
229
|
+
totalModels: allModels.length,
|
|
230
|
+
failedModels: this.failedFreeModels.size,
|
|
231
|
+
connectedProviders: response.connected
|
|
232
|
+
});
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
log.debug("Found cheapest available model for warmup", {
|
|
236
|
+
providerID: availableModel.providerID,
|
|
237
|
+
modelID: availableModel.modelID,
|
|
238
|
+
name: availableModel.name,
|
|
239
|
+
inputCost: availableModel.inputCost,
|
|
240
|
+
releaseDate: availableModel.releaseDate,
|
|
241
|
+
totalModels: allModels.length,
|
|
242
|
+
failedModels: this.failedFreeModels.size,
|
|
243
|
+
connectedProviders: response.connected
|
|
244
|
+
});
|
|
245
|
+
return {
|
|
246
|
+
providerID: availableModel.providerID,
|
|
247
|
+
modelID: availableModel.modelID
|
|
248
|
+
};
|
|
249
|
+
} catch (error) {
|
|
250
|
+
log.warn("Failed to get cheapest model", { error });
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
172
255
|
deleteSession(_0) {
|
|
173
256
|
return __async(this, arguments, function* (sessionId, retries = DEFAULT_RETRIES) {
|
|
174
257
|
const timer = log.timer("deleteSession", { sessionId, retries });
|
|
@@ -239,23 +322,44 @@ class OpenCodeAPI {
|
|
|
239
322
|
throw lastError;
|
|
240
323
|
});
|
|
241
324
|
}
|
|
242
|
-
warmupChromeMcp(viteOrigin) {
|
|
325
|
+
warmupChromeMcp(projectDir, viteOrigin) {
|
|
243
326
|
return __async(this, null, function* () {
|
|
244
327
|
if (!this.warmupChromeMcpConfig) return;
|
|
245
328
|
const timer = log.timer("warmupChromeMcp", { viteOrigin });
|
|
246
329
|
let warmupSessionId = null;
|
|
330
|
+
let freeModel = null;
|
|
331
|
+
const chromeAvailable = yield checkChromeDevToolsAvailable();
|
|
332
|
+
if (!chromeAvailable) {
|
|
333
|
+
const error = new ChromeMcpWarmupError(
|
|
334
|
+
ChromeMcpWarmupErrorType.CHROME_NOT_CONNECTED,
|
|
335
|
+
"Chrome DevTools Protocol is not available",
|
|
336
|
+
"Chrome remote debugging is not enabled or not running on port 9222. Please enable Chrome remote debugging first."
|
|
337
|
+
);
|
|
338
|
+
log.warn("Chrome DevTools not available", {
|
|
339
|
+
port: CHROME_DEVTOOLS_PORT,
|
|
340
|
+
hint: "Enable Chrome remote debugging at chrome://inspect/#remote-debugging"
|
|
341
|
+
});
|
|
342
|
+
timer.end("Chrome DevTools not available");
|
|
343
|
+
throw error;
|
|
344
|
+
}
|
|
345
|
+
log.debug("Chrome DevTools is available, proceeding with warmup");
|
|
247
346
|
try {
|
|
248
|
-
const warmupSession = yield this.createSession(
|
|
347
|
+
const warmupSession = yield this.createSession(
|
|
348
|
+
projectDir,
|
|
349
|
+
DEFAULT_RETRIES,
|
|
350
|
+
"__chrome_mcp_warmup__"
|
|
351
|
+
);
|
|
249
352
|
warmupSessionId = warmupSession.id;
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
353
|
+
freeModel = yield this.getCheapestModel();
|
|
354
|
+
if (freeModel) {
|
|
355
|
+
log.debug("Using cheapest model for warmup", {
|
|
356
|
+
providerID: freeModel.providerID,
|
|
357
|
+
modelID: freeModel.modelID
|
|
358
|
+
});
|
|
359
|
+
} else {
|
|
360
|
+
log.debug("No model available, using default model");
|
|
361
|
+
}
|
|
362
|
+
const WARMUP_TIMEOUT = 6e4;
|
|
259
363
|
const data = yield this.createHttpRequest(
|
|
260
364
|
{
|
|
261
365
|
hostname: this.hostname,
|
|
@@ -264,21 +368,87 @@ class OpenCodeAPI {
|
|
|
264
368
|
method: "POST",
|
|
265
369
|
headers: { "Content-Type": "application/json" }
|
|
266
370
|
},
|
|
267
|
-
JSON.stringify({
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
371
|
+
JSON.stringify(__spreadValues({
|
|
372
|
+
parts: [
|
|
373
|
+
{
|
|
374
|
+
type: "text",
|
|
375
|
+
text: "Test if the chrome-devtools_list_pages tool is available. If available, reply with: ready. If not available, explain why."
|
|
376
|
+
}
|
|
377
|
+
]
|
|
378
|
+
}, freeModel && {
|
|
379
|
+
model: {
|
|
380
|
+
providerID: freeModel.providerID,
|
|
381
|
+
modelID: freeModel.modelID
|
|
382
|
+
}
|
|
383
|
+
})),
|
|
271
384
|
WARMUP_TIMEOUT
|
|
272
385
|
);
|
|
273
386
|
const responseText = extractTextFromResponse(data);
|
|
274
|
-
if (!
|
|
275
|
-
throw new
|
|
387
|
+
if (!responseText) {
|
|
388
|
+
throw new ChromeMcpWarmupError(
|
|
389
|
+
ChromeMcpWarmupErrorType.AI_RESPONSE_ERROR,
|
|
390
|
+
"AI did not respond to the warmup request",
|
|
391
|
+
"Empty response from AI"
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
const lowerResponse = responseText.toLowerCase();
|
|
395
|
+
if (!lowerResponse.includes("ready")) {
|
|
396
|
+
throw new ChromeMcpWarmupError(
|
|
397
|
+
ChromeMcpWarmupErrorType.AI_RESPONSE_ERROR,
|
|
398
|
+
"AI response does not indicate success",
|
|
399
|
+
`AI responded with: ${responseText.substring(0, 200)}`
|
|
400
|
+
);
|
|
276
401
|
}
|
|
277
402
|
timer.end("Chrome MCP warmed up");
|
|
278
403
|
} catch (e) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
404
|
+
if (e instanceof ChromeMcpWarmupError) {
|
|
405
|
+
if (e.type === ChromeMcpWarmupErrorType.SESSION_ERROR) {
|
|
406
|
+
timer.end("Session creation failed");
|
|
407
|
+
}
|
|
408
|
+
log.warn(`Chrome MCP warmup failed: ${e.type}`, __spreadValues({
|
|
409
|
+
message: e.message,
|
|
410
|
+
details: e.details
|
|
411
|
+
}, freeModel && {
|
|
412
|
+
model: `${freeModel.providerID}/${freeModel.modelID}`
|
|
413
|
+
}));
|
|
414
|
+
timer.end(`Chrome MCP warmup failed: ${e.type}`);
|
|
415
|
+
throw e;
|
|
416
|
+
}
|
|
417
|
+
if (freeModel) {
|
|
418
|
+
this.markModelAsFailed(freeModel.providerID, freeModel.modelID);
|
|
419
|
+
log.debug("Marked model as failed due to warmup error", {
|
|
420
|
+
providerID: freeModel.providerID,
|
|
421
|
+
modelID: freeModel.modelID,
|
|
422
|
+
error: e instanceof Error ? e.message : String(e)
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
426
|
+
if (errorMessage.includes("timeout") || errorMessage.includes("Timeout")) {
|
|
427
|
+
const error2 = new ChromeMcpWarmupError(
|
|
428
|
+
ChromeMcpWarmupErrorType.AI_TIMEOUT,
|
|
429
|
+
"AI response timeout",
|
|
430
|
+
"AI did not respond within 30 seconds. Please check if the OpenCode AI model is properly configured and available."
|
|
431
|
+
);
|
|
432
|
+
log.warn("Chrome MCP warmup timeout", __spreadValues({
|
|
433
|
+
error: errorMessage
|
|
434
|
+
}, freeModel && {
|
|
435
|
+
model: `${freeModel.providerID}/${freeModel.modelID}`
|
|
436
|
+
}));
|
|
437
|
+
timer.end("Chrome MCP warmup timeout");
|
|
438
|
+
throw error2;
|
|
439
|
+
}
|
|
440
|
+
const error = new ChromeMcpWarmupError(
|
|
441
|
+
ChromeMcpWarmupErrorType.UNKNOWN,
|
|
442
|
+
"Unknown error during Chrome MCP warmup",
|
|
443
|
+
errorMessage
|
|
444
|
+
);
|
|
445
|
+
log.warn("Chrome MCP warmup failed with unknown error", __spreadValues({
|
|
446
|
+
error: errorMessage
|
|
447
|
+
}, freeModel && {
|
|
448
|
+
model: `${freeModel.providerID}/${freeModel.modelID}`
|
|
449
|
+
}));
|
|
450
|
+
timer.end("Chrome MCP warmup failed");
|
|
451
|
+
throw error;
|
|
282
452
|
} finally {
|
|
283
453
|
if (warmupSessionId) {
|
|
284
454
|
try {
|
|
@@ -293,43 +463,63 @@ class OpenCodeAPI {
|
|
|
293
463
|
}
|
|
294
464
|
});
|
|
295
465
|
}
|
|
296
|
-
getOrCreateSession() {
|
|
466
|
+
getOrCreateSession(projectDir) {
|
|
297
467
|
return __async(this, null, function* () {
|
|
298
|
-
const timer = log.timer("getOrCreateSession");
|
|
299
|
-
const projectDir = process.cwd();
|
|
468
|
+
const timer = log.timer("getOrCreateSession", { projectDir });
|
|
300
469
|
log.debug("Getting sessions...", { projectDir });
|
|
301
|
-
const sessions = yield this.getSessions();
|
|
470
|
+
const sessions = yield this.getSessions(projectDir);
|
|
302
471
|
log.debug(`Found ${sessions.length} sessions`, {
|
|
303
472
|
sessions: sessions.map((s) => ({ id: s.id, directory: s.directory }))
|
|
304
473
|
});
|
|
305
474
|
const matchingSession = sessions.find((s) => s.directory === projectDir);
|
|
306
475
|
if (matchingSession) {
|
|
307
|
-
const url2 = `http://${this.hostname}:${this.
|
|
476
|
+
const url2 = `http://${this.hostname}:${this.getProxyPort()}/${base64Encode(projectDir)}/session/${matchingSession.id}`;
|
|
308
477
|
timer.end(`Using existing session: ${matchingSession.id}`);
|
|
309
478
|
return url2;
|
|
310
479
|
}
|
|
311
480
|
log.debug("Creating new session...", { projectDir });
|
|
312
|
-
const newSession = yield this.createSession();
|
|
313
|
-
const url = `http://${this.hostname}:${this.
|
|
481
|
+
const newSession = yield this.createSession(projectDir);
|
|
482
|
+
const url = `http://${this.hostname}:${this.getProxyPort()}/${base64Encode(projectDir)}/session/${newSession.id}`;
|
|
314
483
|
timer.end(`Created new session: ${newSession.id}`);
|
|
315
484
|
return url;
|
|
316
485
|
});
|
|
317
486
|
}
|
|
318
|
-
retryWarmupChromeMcp(viteOrigin) {
|
|
487
|
+
retryWarmupChromeMcp(projectDir, viteOrigin) {
|
|
319
488
|
return __async(this, null, function* () {
|
|
320
489
|
const timer = log.timer("retryWarmupChromeMcp", { viteOrigin });
|
|
321
490
|
let warmupSessionId = null;
|
|
491
|
+
let freeModel = null;
|
|
492
|
+
const chromeAvailable = yield checkChromeDevToolsAvailable();
|
|
493
|
+
if (!chromeAvailable) {
|
|
494
|
+
const error = new ChromeMcpWarmupError(
|
|
495
|
+
ChromeMcpWarmupErrorType.CHROME_NOT_CONNECTED,
|
|
496
|
+
"Chrome DevTools Protocol is not available",
|
|
497
|
+
"Chrome remote debugging is not enabled or not running on port 9222. Please enable Chrome remote debugging first."
|
|
498
|
+
);
|
|
499
|
+
log.warn("Chrome DevTools not available for retry", {
|
|
500
|
+
port: CHROME_DEVTOOLS_PORT,
|
|
501
|
+
hint: "Enable Chrome remote debugging at chrome://inspect/#remote-debugging"
|
|
502
|
+
});
|
|
503
|
+
timer.end("Chrome DevTools not available for retry");
|
|
504
|
+
return { success: false, error };
|
|
505
|
+
}
|
|
506
|
+
log.debug("Chrome DevTools is available, proceeding with retry warmup");
|
|
322
507
|
try {
|
|
323
|
-
const warmupSession = yield this.createSession(
|
|
508
|
+
const warmupSession = yield this.createSession(
|
|
509
|
+
projectDir,
|
|
510
|
+
DEFAULT_RETRIES,
|
|
511
|
+
"__chrome_mcp_warmup__"
|
|
512
|
+
);
|
|
324
513
|
warmupSessionId = warmupSession.id;
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
514
|
+
freeModel = yield this.getCheapestModel();
|
|
515
|
+
if (freeModel) {
|
|
516
|
+
log.debug("Using cheapest model for retry warmup", {
|
|
517
|
+
providerID: freeModel.providerID,
|
|
518
|
+
modelID: freeModel.modelID
|
|
519
|
+
});
|
|
520
|
+
} else {
|
|
521
|
+
log.debug("No model available for retry, using default model");
|
|
522
|
+
}
|
|
333
523
|
const WARMUP_TIMEOUT = 6e4;
|
|
334
524
|
const data = yield this.createHttpRequest(
|
|
335
525
|
{
|
|
@@ -339,23 +529,89 @@ class OpenCodeAPI {
|
|
|
339
529
|
method: "POST",
|
|
340
530
|
headers: { "Content-Type": "application/json" }
|
|
341
531
|
},
|
|
342
|
-
JSON.stringify({
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
532
|
+
JSON.stringify(__spreadValues({
|
|
533
|
+
parts: [
|
|
534
|
+
{
|
|
535
|
+
type: "text",
|
|
536
|
+
text: "Test if the chrome-devtools_list_pages tool is available. If available, reply with: ready. If not available, explain why."
|
|
537
|
+
}
|
|
538
|
+
]
|
|
539
|
+
}, freeModel && {
|
|
540
|
+
model: {
|
|
541
|
+
providerID: freeModel.providerID,
|
|
542
|
+
modelID: freeModel.modelID
|
|
543
|
+
}
|
|
544
|
+
})),
|
|
346
545
|
WARMUP_TIMEOUT
|
|
347
546
|
);
|
|
348
547
|
log.debug("Chrome MCP warmup response:", { data });
|
|
349
548
|
const responseText = extractTextFromResponse(data);
|
|
350
|
-
if (!
|
|
351
|
-
throw new
|
|
549
|
+
if (!responseText) {
|
|
550
|
+
throw new ChromeMcpWarmupError(
|
|
551
|
+
ChromeMcpWarmupErrorType.AI_RESPONSE_ERROR,
|
|
552
|
+
"AI did not respond to the warmup request",
|
|
553
|
+
"Empty response from AI"
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
const lowerResponse = responseText.toLowerCase();
|
|
557
|
+
if (!lowerResponse.includes("ready")) {
|
|
558
|
+
throw new ChromeMcpWarmupError(
|
|
559
|
+
ChromeMcpWarmupErrorType.AI_RESPONSE_ERROR,
|
|
560
|
+
"AI response does not indicate success",
|
|
561
|
+
`AI responded with: ${responseText.substring(0, 200)}`
|
|
562
|
+
);
|
|
352
563
|
}
|
|
353
564
|
timer.end("Chrome MCP warmed up successfully");
|
|
354
|
-
return true;
|
|
565
|
+
return { success: true };
|
|
355
566
|
} catch (e) {
|
|
356
|
-
|
|
567
|
+
if (e instanceof ChromeMcpWarmupError) {
|
|
568
|
+
if (e.type === ChromeMcpWarmupErrorType.SESSION_ERROR) {
|
|
569
|
+
timer.end("Session creation failed");
|
|
570
|
+
}
|
|
571
|
+
log.warn(`Chrome MCP warmup retry failed: ${e.type}`, __spreadValues({
|
|
572
|
+
message: e.message,
|
|
573
|
+
details: e.details
|
|
574
|
+
}, freeModel && {
|
|
575
|
+
model: `${freeModel.providerID}/${freeModel.modelID}`
|
|
576
|
+
}));
|
|
577
|
+
timer.end(`Chrome MCP warmup retry failed: ${e.type}`);
|
|
578
|
+
return { success: false, error: e };
|
|
579
|
+
}
|
|
580
|
+
if (freeModel) {
|
|
581
|
+
this.markModelAsFailed(freeModel.providerID, freeModel.modelID);
|
|
582
|
+
log.debug("Marked model as failed due to retry warmup error", {
|
|
583
|
+
providerID: freeModel.providerID,
|
|
584
|
+
modelID: freeModel.modelID,
|
|
585
|
+
error: e instanceof Error ? e.message : String(e)
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
589
|
+
if (errorMessage.includes("timeout") || errorMessage.includes("Timeout")) {
|
|
590
|
+
const error2 = new ChromeMcpWarmupError(
|
|
591
|
+
ChromeMcpWarmupErrorType.AI_TIMEOUT,
|
|
592
|
+
"AI response timeout",
|
|
593
|
+
"AI did not respond within 60 seconds. Please check if the OpenCode AI model is properly configured and available."
|
|
594
|
+
);
|
|
595
|
+
log.warn("Chrome MCP warmup retry timeout", __spreadValues({
|
|
596
|
+
error: errorMessage
|
|
597
|
+
}, freeModel && {
|
|
598
|
+
model: `${freeModel.providerID}/${freeModel.modelID}`
|
|
599
|
+
}));
|
|
600
|
+
timer.end("Chrome MCP warmup retry timeout");
|
|
601
|
+
return { success: false, error: error2 };
|
|
602
|
+
}
|
|
603
|
+
const error = new ChromeMcpWarmupError(
|
|
604
|
+
ChromeMcpWarmupErrorType.UNKNOWN,
|
|
605
|
+
"Unknown error during Chrome MCP warmup retry",
|
|
606
|
+
errorMessage
|
|
607
|
+
);
|
|
608
|
+
log.warn("Chrome MCP warmup retry failed with unknown error", __spreadValues({
|
|
609
|
+
error: errorMessage
|
|
610
|
+
}, freeModel && {
|
|
611
|
+
model: `${freeModel.providerID}/${freeModel.modelID}`
|
|
612
|
+
}));
|
|
357
613
|
timer.end("Chrome MCP warmup retry failed");
|
|
358
|
-
return false;
|
|
614
|
+
return { success: false, error };
|
|
359
615
|
} finally {
|
|
360
616
|
if (warmupSessionId) {
|
|
361
617
|
try {
|