vite-plugin-opencode-assistant 1.0.3 → 1.0.5
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.d.ts +1 -0
- package/es/client/index.js +328 -0
- package/es/core/api.d.ts +14 -0
- package/es/core/api.js +294 -0
- package/es/core/injector.d.ts +2 -0
- package/es/core/injector.js +11 -0
- package/es/core/service.d.ts +18 -0
- package/es/core/service.js +163 -0
- package/es/endpoints/context.d.ts +3 -0
- package/es/endpoints/context.js +114 -0
- package/es/endpoints/index.d.ts +4 -0
- package/es/endpoints/index.js +16 -0
- package/es/endpoints/sessions.d.ts +3 -0
- package/es/endpoints/sessions.js +79 -0
- package/es/endpoints/sse.d.ts +3 -0
- package/es/endpoints/sse.js +56 -0
- package/es/endpoints/start.d.ts +3 -0
- package/es/endpoints/start.js +35 -0
- package/es/endpoints/types.d.ts +13 -0
- package/es/endpoints/widget.d.ts +3 -0
- package/es/endpoints/widget.js +57 -0
- package/es/index.d.ts +3 -0
- package/es/index.js +168 -0
- package/es/utils/paths.d.ts +3 -0
- package/es/utils/paths.js +38 -0
- package/es/utils/system.js +241 -0
- package/lib/client/index.d.ts +1 -0
- package/lib/client/index.js +328 -0
- package/lib/client.js +5597 -0
- package/lib/core/api.d.ts +14 -0
- package/lib/core/api.js +321 -0
- package/lib/core/injector.d.ts +2 -0
- package/lib/core/injector.js +34 -0
- package/lib/core/service.d.ts +18 -0
- package/lib/core/service.js +180 -0
- package/lib/endpoints/context.d.ts +3 -0
- package/lib/endpoints/context.js +137 -0
- package/lib/endpoints/index.d.ts +4 -0
- package/lib/endpoints/index.js +41 -0
- package/lib/endpoints/sessions.d.ts +3 -0
- package/lib/endpoints/sessions.js +102 -0
- package/lib/endpoints/sse.d.ts +3 -0
- package/lib/endpoints/sse.js +79 -0
- package/lib/endpoints/start.d.ts +3 -0
- package/lib/endpoints/start.js +58 -0
- package/lib/endpoints/types.d.ts +13 -0
- package/lib/endpoints/types.js +15 -0
- package/lib/endpoints/widget.d.ts +3 -0
- package/lib/endpoints/widget.js +90 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +190 -0
- package/lib/style.css +1 -0
- package/lib/utils/paths.d.ts +3 -0
- package/lib/utils/paths.js +73 -0
- package/lib/utils/system.d.ts +5 -0
- package/lib/utils/system.js +274 -0
- package/package.json +29 -31
- package/README.md +0 -282
- package/dist/constants.d.ts +0 -73
- package/dist/constants.js +0 -74
- package/dist/constants.js.map +0 -1
- package/dist/logger.d.ts +0 -64
- package/dist/logger.js +0 -311
- package/dist/logger.js.map +0 -1
- package/dist/opencode/plugins/page-context.d.ts +0 -7
- package/dist/opencode/plugins/page-context.js +0 -345
- package/dist/opencode/plugins/page-context.js.map +0 -1
- package/dist/opencode/web.d.ts +0 -3
- package/dist/opencode/web.js +0 -81
- package/dist/opencode/web.js.map +0 -1
- package/dist/types.d.ts +0 -124
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/vite/client.js +0 -2288
- package/dist/vite/client.js.map +0 -1
- package/dist/vite/index.d.ts +0 -3
- package/dist/vite/index.js +0 -520
- package/dist/vite/index.js.map +0 -1
- package/dist/vite/injector.d.ts +0 -2
- package/dist/vite/injector.js +0 -6
- package/dist/vite/injector.js.map +0 -1
- package/dist/vite/utils.js +0 -206
- package/dist/vite/utils.js.map +0 -1
- /package/{dist/vite/client.d.ts → es/endpoints/types.js} +0 -0
- /package/{dist/vite/utils.d.ts → es/utils/system.d.ts} +0 -0
package/dist/vite/index.js
DELETED
|
@@ -1,520 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import http from 'http';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import Inspector from 'unplugin-vue-inspector/vite';
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = path.dirname(__filename);
|
|
8
|
-
import { startOpenCodeWeb } from '../opencode/web.js';
|
|
9
|
-
import { injectWidget } from './injector.js';
|
|
10
|
-
import { checkOpenCodeInstalled, findAvailablePort, waitForServer, killOrphanOpenCodeProcesses } from './utils.js';
|
|
11
|
-
import { DEFAULT_CONFIG, DEFAULT_RETRIES, RETRY_DELAY, WIDGET_SCRIPT_PATH, CONTEXT_API_PATH, START_API_PATH, SESSIONS_API_PATH, SSE_EVENTS_PATH, SERVER_START_TIMEOUT, } from '../constants.js';
|
|
12
|
-
import { setVerbose, PerformanceTimer, RequestContext, createLogger, } from '../logger.js';
|
|
13
|
-
export default function opencodePlugin(options = {}) {
|
|
14
|
-
const plugins = [];
|
|
15
|
-
plugins.push(...Inspector({
|
|
16
|
-
enabled: false,
|
|
17
|
-
toggleButtonVisibility: 'never',
|
|
18
|
-
toggleComboKey: false,
|
|
19
|
-
}));
|
|
20
|
-
plugins.push(createOpenCodePlugin(options));
|
|
21
|
-
return plugins;
|
|
22
|
-
}
|
|
23
|
-
function createOpenCodePlugin(options = {}) {
|
|
24
|
-
let webProcess = null;
|
|
25
|
-
let sessionUrl = null;
|
|
26
|
-
let actualWebPort = DEFAULT_CONFIG.webPort;
|
|
27
|
-
let isStarted = false;
|
|
28
|
-
let startPromise = null;
|
|
29
|
-
let pageContext = { url: '', title: '' };
|
|
30
|
-
const sseClients = new Set();
|
|
31
|
-
const config = { ...DEFAULT_CONFIG, ...options };
|
|
32
|
-
setVerbose(config.verbose);
|
|
33
|
-
const log = createLogger('Plugin');
|
|
34
|
-
function base64Encode(str) {
|
|
35
|
-
return Buffer.from(str).toString('base64');
|
|
36
|
-
}
|
|
37
|
-
function sleep(ms) {
|
|
38
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
39
|
-
}
|
|
40
|
-
function createHttpRequest(options, body) {
|
|
41
|
-
const timer = new PerformanceTimer('HTTP Request', {
|
|
42
|
-
operation: `${options.method || 'GET'} ${options.path}`
|
|
43
|
-
});
|
|
44
|
-
return new Promise((resolve, reject) => {
|
|
45
|
-
const req = http.request(options, (res) => {
|
|
46
|
-
let data = '';
|
|
47
|
-
res.on('data', chunk => data += chunk);
|
|
48
|
-
res.on('end', () => {
|
|
49
|
-
try {
|
|
50
|
-
const result = JSON.parse(data);
|
|
51
|
-
timer.end(`✓ Status: ${res.statusCode}`);
|
|
52
|
-
resolve(result);
|
|
53
|
-
}
|
|
54
|
-
catch (e) {
|
|
55
|
-
timer.end('❌ JSON parse error');
|
|
56
|
-
reject(new Error(`JSON parse error: ${data.substring(0, 100)}`));
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
req.on('error', (e) => {
|
|
61
|
-
timer.end('❌ Request failed');
|
|
62
|
-
reject(e);
|
|
63
|
-
});
|
|
64
|
-
if (body)
|
|
65
|
-
req.write(body);
|
|
66
|
-
req.end();
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
async function getSessions(retries = DEFAULT_RETRIES) {
|
|
70
|
-
const timer = log.timer('getSessions', { retries });
|
|
71
|
-
let lastError = null;
|
|
72
|
-
for (let i = 0; i < retries; i++) {
|
|
73
|
-
try {
|
|
74
|
-
log.debug(`Attempt ${i + 1}/${retries}`, { operation: 'getSessions' });
|
|
75
|
-
const sessions = await createHttpRequest({
|
|
76
|
-
hostname: config.hostname,
|
|
77
|
-
port: actualWebPort,
|
|
78
|
-
path: '/session',
|
|
79
|
-
});
|
|
80
|
-
timer.end(`Found ${sessions.length} sessions`);
|
|
81
|
-
return sessions;
|
|
82
|
-
}
|
|
83
|
-
catch (e) {
|
|
84
|
-
lastError = e instanceof Error ? e : new Error(String(e));
|
|
85
|
-
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { operation: 'getSessions' });
|
|
86
|
-
if (i < retries - 1) {
|
|
87
|
-
log.debug(`Retrying in ${RETRY_DELAY}ms...`, { operation: 'getSessions' });
|
|
88
|
-
await sleep(RETRY_DELAY);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
timer.end('❌ All retries exhausted');
|
|
93
|
-
throw lastError;
|
|
94
|
-
}
|
|
95
|
-
async function createSession(retries = DEFAULT_RETRIES) {
|
|
96
|
-
const timer = log.timer('createSession', { retries });
|
|
97
|
-
let lastError = null;
|
|
98
|
-
for (let i = 0; i < retries; i++) {
|
|
99
|
-
try {
|
|
100
|
-
log.debug(`Attempt ${i + 1}/${retries}`, { operation: 'createSession' });
|
|
101
|
-
const session = await createHttpRequest({
|
|
102
|
-
hostname: config.hostname,
|
|
103
|
-
port: actualWebPort,
|
|
104
|
-
path: '/session',
|
|
105
|
-
method: 'POST',
|
|
106
|
-
});
|
|
107
|
-
timer.end(`Created session: ${session.id}`);
|
|
108
|
-
return session;
|
|
109
|
-
}
|
|
110
|
-
catch (e) {
|
|
111
|
-
lastError = e instanceof Error ? e : new Error(String(e));
|
|
112
|
-
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { operation: 'createSession' });
|
|
113
|
-
if (i < retries - 1) {
|
|
114
|
-
log.debug(`Retrying in ${RETRY_DELAY}ms...`, { operation: 'createSession' });
|
|
115
|
-
await sleep(RETRY_DELAY);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
timer.end('❌ All retries exhausted');
|
|
120
|
-
throw lastError;
|
|
121
|
-
}
|
|
122
|
-
async function deleteSession(sessionId, retries = DEFAULT_RETRIES) {
|
|
123
|
-
const timer = log.timer('deleteSession', { sessionId, retries });
|
|
124
|
-
let lastError = null;
|
|
125
|
-
for (let i = 0; i < retries; i++) {
|
|
126
|
-
try {
|
|
127
|
-
log.debug(`Attempt ${i + 1}/${retries}`, { operation: 'deleteSession', sessionId });
|
|
128
|
-
await createHttpRequest({
|
|
129
|
-
hostname: config.hostname,
|
|
130
|
-
port: actualWebPort,
|
|
131
|
-
path: `/session/${sessionId}`,
|
|
132
|
-
method: 'DELETE',
|
|
133
|
-
});
|
|
134
|
-
timer.end(`Deleted session: ${sessionId}`);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
catch (e) {
|
|
138
|
-
lastError = e instanceof Error ? e : new Error(String(e));
|
|
139
|
-
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { operation: 'deleteSession', sessionId });
|
|
140
|
-
if (i < retries - 1) {
|
|
141
|
-
log.debug(`Retrying in ${RETRY_DELAY}ms...`, { operation: 'deleteSession', sessionId });
|
|
142
|
-
await sleep(RETRY_DELAY);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
timer.end('❌ All retries exhausted');
|
|
147
|
-
throw lastError;
|
|
148
|
-
}
|
|
149
|
-
async function getOrCreateSession() {
|
|
150
|
-
const timer = log.timer('getOrCreateSession');
|
|
151
|
-
const projectDir = process.cwd();
|
|
152
|
-
log.debug('Getting sessions...', { projectDir });
|
|
153
|
-
const sessions = await getSessions();
|
|
154
|
-
log.debug(`Found ${sessions.length} sessions`, {
|
|
155
|
-
sessions: sessions.map(s => ({ id: s.id, directory: s.directory }))
|
|
156
|
-
});
|
|
157
|
-
const matchingSession = sessions.find(s => s.directory === projectDir);
|
|
158
|
-
if (matchingSession) {
|
|
159
|
-
const url = `http://${config.hostname}:${actualWebPort}/${base64Encode(projectDir)}/session/${matchingSession.id}`;
|
|
160
|
-
timer.end(`Using existing session: ${matchingSession.id}`);
|
|
161
|
-
return url;
|
|
162
|
-
}
|
|
163
|
-
log.debug('Creating new session...', { projectDir });
|
|
164
|
-
const newSession = await createSession();
|
|
165
|
-
const url = `http://${config.hostname}:${actualWebPort}/${base64Encode(projectDir)}/session/${newSession.id}`;
|
|
166
|
-
timer.end(`Created new session: ${newSession.id}`);
|
|
167
|
-
return url;
|
|
168
|
-
}
|
|
169
|
-
function setupOpenCodePlugin() {
|
|
170
|
-
const timer = log.timer('setupOpenCodePlugin');
|
|
171
|
-
const projectDir = process.cwd();
|
|
172
|
-
const cacheDir = path.join(projectDir, 'node_modules', '.cache', 'opencode');
|
|
173
|
-
const pluginsDir = path.join(cacheDir, 'plugins');
|
|
174
|
-
log.debug('Setting up plugin directory', { cacheDir, pluginsDir });
|
|
175
|
-
if (!fs.existsSync(pluginsDir)) {
|
|
176
|
-
fs.mkdirSync(pluginsDir, { recursive: true });
|
|
177
|
-
log.debug('Created plugins directory', { pluginsDir });
|
|
178
|
-
}
|
|
179
|
-
const pluginSourcePath = path.join(__dirname, '..', 'opencode', 'plugins', 'page-context.js');
|
|
180
|
-
const pluginTargetPath = path.join(pluginsDir, 'page-context.js');
|
|
181
|
-
if (fs.existsSync(pluginSourcePath)) {
|
|
182
|
-
fs.copyFileSync(pluginSourcePath, pluginTargetPath);
|
|
183
|
-
log.debug('Plugin installed', { source: pluginSourcePath, target: pluginTargetPath });
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
log.warn('Plugin source not found', { path: pluginSourcePath });
|
|
187
|
-
}
|
|
188
|
-
timer.end();
|
|
189
|
-
return cacheDir;
|
|
190
|
-
}
|
|
191
|
-
async function startServices(corsOrigins, contextApiUrl) {
|
|
192
|
-
if (isStarted && webProcess) {
|
|
193
|
-
log.debug('Services already started, skipping');
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
if (startPromise) {
|
|
197
|
-
log.debug('Waiting for existing start promise');
|
|
198
|
-
return startPromise;
|
|
199
|
-
}
|
|
200
|
-
startPromise = (async () => {
|
|
201
|
-
const timer = log.timer('startServices', { corsOrigins, contextApiUrl });
|
|
202
|
-
log.info('Starting OpenCode services...');
|
|
203
|
-
const orphanCount = await killOrphanOpenCodeProcesses();
|
|
204
|
-
if (orphanCount > 0) {
|
|
205
|
-
log.debug(`Killed ${orphanCount} orphan OpenCode process(es)`);
|
|
206
|
-
}
|
|
207
|
-
if (!await checkOpenCodeInstalled()) {
|
|
208
|
-
log.error(`OpenCode is not installed!
|
|
209
|
-
|
|
210
|
-
Please install OpenCode first:
|
|
211
|
-
|
|
212
|
-
# Using Homebrew (macOS)
|
|
213
|
-
brew install opencode-ai/tap/opencode
|
|
214
|
-
|
|
215
|
-
# Or using the install script
|
|
216
|
-
curl -fsSL https://opencode.ai/install | bash
|
|
217
|
-
`);
|
|
218
|
-
timer.end('❌ OpenCode not installed');
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
timer.checkpoint('OpenCode installation verified');
|
|
222
|
-
actualWebPort = await findAvailablePort(config.webPort, config.hostname);
|
|
223
|
-
if (actualWebPort !== config.webPort) {
|
|
224
|
-
log.info(`Port ${config.webPort} is in use, using ${actualWebPort} instead`);
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
log.debug(`Using port ${actualWebPort}`);
|
|
228
|
-
}
|
|
229
|
-
timer.checkpoint('Port allocated');
|
|
230
|
-
const configDir = setupOpenCodePlugin();
|
|
231
|
-
timer.checkpoint('Plugin setup complete');
|
|
232
|
-
log.debug('Starting OpenCode Web process...', {
|
|
233
|
-
port: actualWebPort,
|
|
234
|
-
hostname: config.hostname,
|
|
235
|
-
configDir
|
|
236
|
-
});
|
|
237
|
-
webProcess = startOpenCodeWeb({
|
|
238
|
-
port: actualWebPort,
|
|
239
|
-
hostname: config.hostname,
|
|
240
|
-
serverUrl: '',
|
|
241
|
-
cwd: process.cwd(),
|
|
242
|
-
configDir,
|
|
243
|
-
corsOrigins,
|
|
244
|
-
contextApiUrl,
|
|
245
|
-
});
|
|
246
|
-
timer.checkpoint('Web process started');
|
|
247
|
-
await waitForServer(`http://${config.hostname}:${actualWebPort}`, SERVER_START_TIMEOUT);
|
|
248
|
-
log.info(`OpenCode Web started at http://${config.hostname}:${actualWebPort}`);
|
|
249
|
-
try {
|
|
250
|
-
sessionUrl = await getOrCreateSession();
|
|
251
|
-
timer.checkpoint('Session created');
|
|
252
|
-
log.debug(`Session URL: ${sessionUrl}`);
|
|
253
|
-
}
|
|
254
|
-
catch (e) {
|
|
255
|
-
log.warn('Failed to get/create session', { error: e });
|
|
256
|
-
}
|
|
257
|
-
isStarted = true;
|
|
258
|
-
timer.end('✓ Services started successfully');
|
|
259
|
-
})();
|
|
260
|
-
return startPromise;
|
|
261
|
-
}
|
|
262
|
-
async function stopServices() {
|
|
263
|
-
const timer = log.timer('stopServices');
|
|
264
|
-
log.info('Stopping OpenCode services...');
|
|
265
|
-
if (webProcess) {
|
|
266
|
-
log.debug('Killing web process', { pid: webProcess.pid });
|
|
267
|
-
webProcess.kill('SIGTERM');
|
|
268
|
-
webProcess = null;
|
|
269
|
-
}
|
|
270
|
-
isStarted = false;
|
|
271
|
-
startPromise = null;
|
|
272
|
-
timer.end('✓ Services stopped');
|
|
273
|
-
}
|
|
274
|
-
function handleContextRequest(req, res) {
|
|
275
|
-
const ctx = new RequestContext(req.method || 'GET', CONTEXT_API_PATH);
|
|
276
|
-
res.setHeader('Content-Type', 'application/json');
|
|
277
|
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
278
|
-
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
279
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
280
|
-
if (req.method === 'OPTIONS') {
|
|
281
|
-
res.writeHead(200);
|
|
282
|
-
res.end();
|
|
283
|
-
ctx.end(200);
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
if (req.method === 'GET') {
|
|
287
|
-
res.writeHead(200);
|
|
288
|
-
res.end(JSON.stringify(pageContext));
|
|
289
|
-
ctx.end(200);
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
if (req.method === 'DELETE') {
|
|
293
|
-
pageContext.selectedElements = [];
|
|
294
|
-
log.debug('Selected elements cleared', { sseClients: sseClients.size });
|
|
295
|
-
let sentCount = 0;
|
|
296
|
-
sseClients.forEach(client => {
|
|
297
|
-
try {
|
|
298
|
-
client.write(`data: ${JSON.stringify({ type: 'CLEAR_ELEMENTS' })}\n\n`);
|
|
299
|
-
sentCount++;
|
|
300
|
-
}
|
|
301
|
-
catch (e) {
|
|
302
|
-
log.debug('Failed to send SSE message', { error: e });
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
log.debug('SSE messages sent', { count: sentCount, totalClients: sseClients.size });
|
|
306
|
-
res.writeHead(200);
|
|
307
|
-
res.end(JSON.stringify({ success: true }));
|
|
308
|
-
ctx.end(200);
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
if (req.method === 'POST') {
|
|
312
|
-
let body = '';
|
|
313
|
-
req.on('data', chunk => body += chunk);
|
|
314
|
-
req.on('end', () => {
|
|
315
|
-
try {
|
|
316
|
-
const data = JSON.parse(body);
|
|
317
|
-
pageContext = {
|
|
318
|
-
url: data.url || '',
|
|
319
|
-
title: data.title || '',
|
|
320
|
-
selectedElements: data.selectedElements || [],
|
|
321
|
-
};
|
|
322
|
-
log.debug('Context updated', {
|
|
323
|
-
url: pageContext.url,
|
|
324
|
-
title: pageContext.title,
|
|
325
|
-
selectedElementsCount: pageContext.selectedElements?.length || 0
|
|
326
|
-
});
|
|
327
|
-
if (pageContext.selectedElements && pageContext.selectedElements.length > 0) {
|
|
328
|
-
log.debug('Selected elements details', {
|
|
329
|
-
elements: pageContext.selectedElements.map(el => ({
|
|
330
|
-
filePath: el.filePath,
|
|
331
|
-
line: el.line,
|
|
332
|
-
text: el.innerText?.substring(0, 50)
|
|
333
|
-
}))
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
res.writeHead(200);
|
|
337
|
-
res.end(JSON.stringify({ success: true }));
|
|
338
|
-
ctx.end(200);
|
|
339
|
-
}
|
|
340
|
-
catch (e) {
|
|
341
|
-
log.debug('Invalid JSON in request body', { error: e });
|
|
342
|
-
res.writeHead(400);
|
|
343
|
-
res.end(JSON.stringify({ error: 'Invalid JSON' }));
|
|
344
|
-
ctx.end(400);
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
res.writeHead(405);
|
|
350
|
-
res.end(JSON.stringify({ error: 'Method not allowed' }));
|
|
351
|
-
ctx.end(405);
|
|
352
|
-
}
|
|
353
|
-
return {
|
|
354
|
-
name: 'vite-plugin-opencode',
|
|
355
|
-
async configureServer(server) {
|
|
356
|
-
if (!config.enabled) {
|
|
357
|
-
log.debug('Plugin disabled, skipping configuration');
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
const timer = log.timer('configureServer');
|
|
361
|
-
server.middlewares.use(WIDGET_SCRIPT_PATH, async (_req, res) => {
|
|
362
|
-
const ctx = new RequestContext('GET', WIDGET_SCRIPT_PATH);
|
|
363
|
-
const widgetPath = path.join(__dirname, 'client.js');
|
|
364
|
-
if (fs.existsSync(widgetPath)) {
|
|
365
|
-
res.setHeader('Content-Type', 'application/javascript');
|
|
366
|
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
367
|
-
fs.createReadStream(widgetPath).pipe(res);
|
|
368
|
-
ctx.end(200);
|
|
369
|
-
}
|
|
370
|
-
else {
|
|
371
|
-
res.writeHead(404);
|
|
372
|
-
res.end('Widget script not found');
|
|
373
|
-
ctx.end(404);
|
|
374
|
-
}
|
|
375
|
-
});
|
|
376
|
-
server.middlewares.use(CONTEXT_API_PATH, async (req, res) => {
|
|
377
|
-
handleContextRequest(req, res);
|
|
378
|
-
});
|
|
379
|
-
server.middlewares.use(START_API_PATH, async (_req, res) => {
|
|
380
|
-
const ctx = new RequestContext('GET', START_API_PATH);
|
|
381
|
-
res.setHeader('Content-Type', 'application/json');
|
|
382
|
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
383
|
-
res.writeHead(200);
|
|
384
|
-
res.end(JSON.stringify({ success: true, sessionUrl }));
|
|
385
|
-
ctx.end(200);
|
|
386
|
-
});
|
|
387
|
-
server.middlewares.use(SSE_EVENTS_PATH, async (req, res) => {
|
|
388
|
-
const ctx = new RequestContext('GET', SSE_EVENTS_PATH);
|
|
389
|
-
res.writeHead(200, {
|
|
390
|
-
'Content-Type': 'text/event-stream',
|
|
391
|
-
'Cache-Control': 'no-cache',
|
|
392
|
-
'Connection': 'keep-alive',
|
|
393
|
-
'Access-Control-Allow-Origin': '*',
|
|
394
|
-
});
|
|
395
|
-
sseClients.add(res);
|
|
396
|
-
log.debug('SSE client connected', { totalClients: sseClients.size });
|
|
397
|
-
res.write(`data: ${JSON.stringify({ type: 'CONNECTED' })}\n\n`);
|
|
398
|
-
req.on('close', () => {
|
|
399
|
-
sseClients.delete(res);
|
|
400
|
-
log.debug('SSE client disconnected', { totalClients: sseClients.size });
|
|
401
|
-
});
|
|
402
|
-
ctx.end(200);
|
|
403
|
-
});
|
|
404
|
-
server.middlewares.use(SESSIONS_API_PATH, async (req, res) => {
|
|
405
|
-
const ctx = new RequestContext(req.method || 'GET', SESSIONS_API_PATH);
|
|
406
|
-
res.setHeader('Content-Type', 'application/json');
|
|
407
|
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
408
|
-
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
409
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
410
|
-
if (req.method === 'OPTIONS') {
|
|
411
|
-
res.writeHead(200);
|
|
412
|
-
res.end();
|
|
413
|
-
ctx.end(200);
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
416
|
-
try {
|
|
417
|
-
if (req.method === 'GET') {
|
|
418
|
-
ctx.checkpoint('Fetching sessions');
|
|
419
|
-
const sessions = await getSessions();
|
|
420
|
-
res.writeHead(200);
|
|
421
|
-
res.end(JSON.stringify(sessions));
|
|
422
|
-
ctx.end(200);
|
|
423
|
-
}
|
|
424
|
-
else if (req.method === 'POST') {
|
|
425
|
-
ctx.checkpoint('Creating session');
|
|
426
|
-
const newSession = await createSession();
|
|
427
|
-
res.writeHead(200);
|
|
428
|
-
res.end(JSON.stringify(newSession));
|
|
429
|
-
ctx.end(200);
|
|
430
|
-
}
|
|
431
|
-
else if (req.method === 'DELETE') {
|
|
432
|
-
const url = new URL(req.url || '', `http://${req.headers.host}`);
|
|
433
|
-
const sessionId = url.searchParams.get('id');
|
|
434
|
-
if (!sessionId) {
|
|
435
|
-
res.writeHead(400);
|
|
436
|
-
res.end(JSON.stringify({ error: 'Session ID is required' }));
|
|
437
|
-
ctx.end(400);
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
ctx.checkpoint(`Deleting session: ${sessionId}`);
|
|
441
|
-
await deleteSession(sessionId);
|
|
442
|
-
res.writeHead(200);
|
|
443
|
-
res.end(JSON.stringify({ success: true }));
|
|
444
|
-
ctx.end(200);
|
|
445
|
-
}
|
|
446
|
-
else {
|
|
447
|
-
res.writeHead(405);
|
|
448
|
-
res.end(JSON.stringify({ error: 'Method not allowed' }));
|
|
449
|
-
ctx.end(405);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
catch (e) {
|
|
453
|
-
log.error('Session API error', { error: e, method: req.method });
|
|
454
|
-
res.writeHead(500);
|
|
455
|
-
res.end(JSON.stringify({ error: String(e) }));
|
|
456
|
-
ctx.error(e);
|
|
457
|
-
}
|
|
458
|
-
});
|
|
459
|
-
server.httpServer?.on('listening', async () => {
|
|
460
|
-
log.debug('Vite server listening event fired');
|
|
461
|
-
const address = server.httpServer?.address();
|
|
462
|
-
let vitePort;
|
|
463
|
-
let viteHost;
|
|
464
|
-
if (address && typeof address === 'object') {
|
|
465
|
-
vitePort = address.port;
|
|
466
|
-
const addr = address.address;
|
|
467
|
-
if (addr === '::' || addr === '::1' || addr === '0.0.0.0' || !addr) {
|
|
468
|
-
viteHost = 'localhost';
|
|
469
|
-
}
|
|
470
|
-
else {
|
|
471
|
-
viteHost = addr;
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
else {
|
|
475
|
-
const host = server.config.server.host;
|
|
476
|
-
vitePort = server.config.server.port || 5173;
|
|
477
|
-
viteHost = typeof host === 'string' && host !== '0.0.0.0' && host !== '::' && host !== '::1' ? host : 'localhost';
|
|
478
|
-
}
|
|
479
|
-
const viteOrigin = `http://${viteHost}:${vitePort}`;
|
|
480
|
-
const contextApiUrl = `http://${viteHost}:${vitePort}${CONTEXT_API_PATH}`;
|
|
481
|
-
log.debug('Vite server ready', { vitePort, viteHost, viteOrigin, contextApiUrl });
|
|
482
|
-
try {
|
|
483
|
-
await startServices([viteOrigin], contextApiUrl);
|
|
484
|
-
}
|
|
485
|
-
catch (e) {
|
|
486
|
-
log.error('Failed to start services', { error: e });
|
|
487
|
-
}
|
|
488
|
-
});
|
|
489
|
-
server.httpServer?.on('close', () => {
|
|
490
|
-
log.debug('HTTP server closing');
|
|
491
|
-
stopServices();
|
|
492
|
-
});
|
|
493
|
-
const cleanup = async () => {
|
|
494
|
-
log.debug('Process cleanup triggered');
|
|
495
|
-
await stopServices();
|
|
496
|
-
process.exit(0);
|
|
497
|
-
};
|
|
498
|
-
process.on('SIGINT', cleanup);
|
|
499
|
-
process.on('SIGTERM', cleanup);
|
|
500
|
-
timer.end('✓ Server configured');
|
|
501
|
-
},
|
|
502
|
-
transformIndexHtml(html) {
|
|
503
|
-
const timer = log.timer('transformIndexHtml');
|
|
504
|
-
const widget = injectWidget({
|
|
505
|
-
webUrl: `http://${config.hostname}:${actualWebPort}`,
|
|
506
|
-
serverUrl: `http://${config.hostname}:${actualWebPort}`,
|
|
507
|
-
position: config.position,
|
|
508
|
-
theme: config.theme,
|
|
509
|
-
open: config.open,
|
|
510
|
-
autoReload: config.autoReload,
|
|
511
|
-
cwd: process.cwd(),
|
|
512
|
-
sessionUrl: sessionUrl || undefined,
|
|
513
|
-
hotkey: config.hotkey,
|
|
514
|
-
});
|
|
515
|
-
timer.end();
|
|
516
|
-
return html.replace('</body>', `${widget}</body>`);
|
|
517
|
-
},
|
|
518
|
-
};
|
|
519
|
-
}
|
|
520
|
-
//# sourceMappingURL=index.js.map
|
package/dist/vite/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Plugin, ViteDevServer } from 'vite'\nimport type { ResultPromise } from 'execa'\nimport path from 'path'\nimport fs from 'fs'\nimport http from 'http'\nimport { fileURLToPath } from 'url'\nimport Inspector from 'unplugin-vue-inspector/vite'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nimport { startOpenCodeWeb } from '../opencode/web.js'\nimport { injectWidget } from './injector.js'\nimport { checkOpenCodeInstalled, findAvailablePort, waitForServer, killOrphanOpenCodeProcesses } from './utils.js'\nimport { OpenCodeOptions, SessionInfo, PageContext } from '../types.js'\nimport {\n DEFAULT_CONFIG,\n DEFAULT_RETRIES,\n RETRY_DELAY,\n WIDGET_SCRIPT_PATH,\n CONTEXT_API_PATH,\n START_API_PATH,\n SESSIONS_API_PATH,\n SSE_EVENTS_PATH,\n SERVER_START_TIMEOUT,\n} from '../constants.js'\nimport {\n setVerbose,\n PerformanceTimer,\n RequestContext,\n createLogger,\n} from '../logger.js'\n\nexport default function opencodePlugin(options: OpenCodeOptions = {}): Plugin[] {\n const plugins: Plugin[] = []\n \n plugins.push(...Inspector({\n enabled: false,\n toggleButtonVisibility: 'never',\n toggleComboKey: false,\n }))\n \n plugins.push(createOpenCodePlugin(options))\n \n return plugins\n}\n\nfunction createOpenCodePlugin(options: OpenCodeOptions = {}): Plugin {\n let webProcess: ResultPromise | null = null\n let sessionUrl: string | null = null\n let actualWebPort: number = DEFAULT_CONFIG.webPort\n let isStarted = false\n let startPromise: Promise<void> | null = null\n let pageContext: PageContext = { url: '', title: '' }\n \n const sseClients: Set<http.ServerResponse> = new Set()\n\n const config = { ...DEFAULT_CONFIG, ...options }\n \n setVerbose(config.verbose)\n \n const log = createLogger('Plugin')\n\n function base64Encode(str: string): string {\n return Buffer.from(str).toString('base64')\n }\n\n function sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n }\n\n function createHttpRequest<T>(options: http.RequestOptions, body?: string): Promise<T> {\n const timer = new PerformanceTimer('HTTP Request', { \n operation: `${options.method || 'GET'} ${options.path}` \n })\n \n return new Promise((resolve, reject) => {\n const req = http.request(options, (res) => {\n let data = ''\n res.on('data', chunk => data += chunk)\n res.on('end', () => {\n try {\n const result = JSON.parse(data)\n timer.end(`✓ Status: ${res.statusCode}`)\n resolve(result)\n } catch (e) {\n timer.end('❌ JSON parse error')\n reject(new Error(`JSON parse error: ${data.substring(0, 100)}`))\n }\n })\n })\n req.on('error', (e) => {\n timer.end('❌ Request failed')\n reject(e)\n })\n if (body) req.write(body)\n req.end()\n })\n }\n\n async function getSessions(retries = DEFAULT_RETRIES): Promise<SessionInfo[]> {\n const timer = log.timer('getSessions', { retries })\n let lastError: Error | null = null\n\n for (let i = 0; i < retries; i++) {\n try {\n log.debug(`Attempt ${i + 1}/${retries}`, { operation: 'getSessions' })\n const sessions = await createHttpRequest<SessionInfo[]>({\n hostname: config.hostname,\n port: actualWebPort,\n path: '/session',\n })\n timer.end(`Found ${sessions.length} sessions`)\n return sessions\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e))\n log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { operation: 'getSessions' })\n if (i < retries - 1) {\n log.debug(`Retrying in ${RETRY_DELAY}ms...`, { operation: 'getSessions' })\n await sleep(RETRY_DELAY)\n }\n }\n }\n\n timer.end('❌ All retries exhausted')\n throw lastError\n }\n\n async function createSession(retries = DEFAULT_RETRIES): Promise<SessionInfo> {\n const timer = log.timer('createSession', { retries })\n let lastError: Error | null = null\n\n for (let i = 0; i < retries; i++) {\n try {\n log.debug(`Attempt ${i + 1}/${retries}`, { operation: 'createSession' })\n const session = await createHttpRequest<SessionInfo>({\n hostname: config.hostname,\n port: actualWebPort,\n path: '/session',\n method: 'POST',\n })\n timer.end(`Created session: ${session.id}`)\n return session\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e))\n log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { operation: 'createSession' })\n if (i < retries - 1) {\n log.debug(`Retrying in ${RETRY_DELAY}ms...`, { operation: 'createSession' })\n await sleep(RETRY_DELAY)\n }\n }\n }\n\n timer.end('❌ All retries exhausted')\n throw lastError\n }\n\n async function deleteSession(sessionId: string, retries = DEFAULT_RETRIES): Promise<void> {\n const timer = log.timer('deleteSession', { sessionId, retries })\n let lastError: Error | null = null\n\n for (let i = 0; i < retries; i++) {\n try {\n log.debug(`Attempt ${i + 1}/${retries}`, { operation: 'deleteSession', sessionId })\n await createHttpRequest<void>({\n hostname: config.hostname,\n port: actualWebPort,\n path: `/session/${sessionId}`,\n method: 'DELETE',\n })\n timer.end(`Deleted session: ${sessionId}`)\n return\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e))\n log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, { operation: 'deleteSession', sessionId })\n if (i < retries - 1) {\n log.debug(`Retrying in ${RETRY_DELAY}ms...`, { operation: 'deleteSession', sessionId })\n await sleep(RETRY_DELAY)\n }\n }\n }\n\n timer.end('❌ All retries exhausted')\n throw lastError\n }\n\n async function getOrCreateSession(): Promise<string> {\n const timer = log.timer('getOrCreateSession')\n const projectDir = process.cwd()\n \n log.debug('Getting sessions...', { projectDir })\n const sessions = await getSessions()\n log.debug(`Found ${sessions.length} sessions`, { \n sessions: sessions.map(s => ({ id: s.id, directory: s.directory })) \n })\n\n const matchingSession = sessions.find(s => s.directory === projectDir)\n\n if (matchingSession) {\n const url = `http://${config.hostname}:${actualWebPort}/${base64Encode(projectDir)}/session/${matchingSession.id}`\n timer.end(`Using existing session: ${matchingSession.id}`)\n return url\n }\n\n log.debug('Creating new session...', { projectDir })\n const newSession = await createSession()\n const url = `http://${config.hostname}:${actualWebPort}/${base64Encode(projectDir)}/session/${newSession.id}`\n timer.end(`Created new session: ${newSession.id}`)\n return url\n }\n\n function setupOpenCodePlugin(): string {\n const timer = log.timer('setupOpenCodePlugin')\n const projectDir = process.cwd()\n const cacheDir = path.join(projectDir, 'node_modules', '.cache', 'opencode')\n const pluginsDir = path.join(cacheDir, 'plugins')\n\n log.debug('Setting up plugin directory', { cacheDir, pluginsDir })\n\n if (!fs.existsSync(pluginsDir)) {\n fs.mkdirSync(pluginsDir, { recursive: true })\n log.debug('Created plugins directory', { pluginsDir })\n }\n\n const pluginSourcePath = path.join(__dirname, '..', 'opencode', 'plugins', 'page-context.js')\n const pluginTargetPath = path.join(pluginsDir, 'page-context.js')\n\n if (fs.existsSync(pluginSourcePath)) {\n fs.copyFileSync(pluginSourcePath, pluginTargetPath)\n log.debug('Plugin installed', { source: pluginSourcePath, target: pluginTargetPath })\n } else {\n log.warn('Plugin source not found', { path: pluginSourcePath })\n }\n\n timer.end()\n return cacheDir\n }\n\n async function startServices(corsOrigins?: string[], contextApiUrl?: string): Promise<void> {\n if (isStarted && webProcess) {\n log.debug('Services already started, skipping')\n return\n }\n if (startPromise) {\n log.debug('Waiting for existing start promise')\n return startPromise\n }\n\n startPromise = (async () => {\n const timer = log.timer('startServices', { corsOrigins, contextApiUrl })\n log.info('Starting OpenCode services...')\n\n const orphanCount = await killOrphanOpenCodeProcesses()\n if (orphanCount > 0) {\n log.debug(`Killed ${orphanCount} orphan OpenCode process(es)`)\n }\n\n if (!await checkOpenCodeInstalled()) {\n log.error(`OpenCode is not installed!\n\nPlease install OpenCode first:\n\n # Using Homebrew (macOS)\n brew install opencode-ai/tap/opencode\n\n # Or using the install script\n curl -fsSL https://opencode.ai/install | bash\n `)\n timer.end('❌ OpenCode not installed')\n return\n }\n\n timer.checkpoint('OpenCode installation verified')\n\n actualWebPort = await findAvailablePort(config.webPort, config.hostname)\n if (actualWebPort !== config.webPort) {\n log.info(`Port ${config.webPort} is in use, using ${actualWebPort} instead`)\n } else {\n log.debug(`Using port ${actualWebPort}`)\n }\n\n timer.checkpoint('Port allocated')\n\n const configDir = setupOpenCodePlugin()\n\n timer.checkpoint('Plugin setup complete')\n\n log.debug('Starting OpenCode Web process...', { \n port: actualWebPort, \n hostname: config.hostname,\n configDir \n })\n \n webProcess = startOpenCodeWeb({\n port: actualWebPort,\n hostname: config.hostname,\n serverUrl: '',\n cwd: process.cwd(),\n configDir,\n corsOrigins,\n contextApiUrl,\n })\n \n timer.checkpoint('Web process started')\n\n await waitForServer(`http://${config.hostname}:${actualWebPort}`, SERVER_START_TIMEOUT)\n log.info(`OpenCode Web started at http://${config.hostname}:${actualWebPort}`)\n\n try {\n sessionUrl = await getOrCreateSession()\n timer.checkpoint('Session created')\n log.debug(`Session URL: ${sessionUrl}`)\n } catch (e) {\n log.warn('Failed to get/create session', { error: e })\n }\n\n isStarted = true\n timer.end('✓ Services started successfully')\n })()\n\n return startPromise\n }\n\n async function stopServices(): Promise<void> {\n const timer = log.timer('stopServices')\n log.info('Stopping OpenCode services...')\n \n if (webProcess) {\n log.debug('Killing web process', { pid: webProcess.pid })\n webProcess.kill('SIGTERM')\n webProcess = null\n }\n \n isStarted = false\n startPromise = null\n timer.end('✓ Services stopped')\n }\n\n function handleContextRequest(req: http.IncomingMessage, res: http.ServerResponse): void {\n const ctx = new RequestContext(req.method || 'GET', CONTEXT_API_PATH)\n \n res.setHeader('Content-Type', 'application/json')\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type')\n\n if (req.method === 'OPTIONS') {\n res.writeHead(200)\n res.end()\n ctx.end(200)\n return\n }\n\n if (req.method === 'GET') {\n res.writeHead(200)\n res.end(JSON.stringify(pageContext))\n ctx.end(200)\n return\n }\n\n if (req.method === 'DELETE') {\n pageContext.selectedElements = []\n log.debug('Selected elements cleared', { sseClients: sseClients.size })\n \n let sentCount = 0\n sseClients.forEach(client => {\n try {\n client.write(`data: ${JSON.stringify({ type: 'CLEAR_ELEMENTS' })}\\n\\n`)\n sentCount++\n } catch (e) {\n log.debug('Failed to send SSE message', { error: e })\n }\n })\n log.debug('SSE messages sent', { count: sentCount, totalClients: sseClients.size })\n \n res.writeHead(200)\n res.end(JSON.stringify({ success: true }))\n ctx.end(200)\n return\n }\n\n if (req.method === 'POST') {\n let body = ''\n req.on('data', chunk => body += chunk)\n req.on('end', () => {\n try {\n const data = JSON.parse(body)\n pageContext = {\n url: data.url || '',\n title: data.title || '',\n selectedElements: data.selectedElements || [],\n }\n log.debug('Context updated', { \n url: pageContext.url, \n title: pageContext.title,\n selectedElementsCount: pageContext.selectedElements?.length || 0 \n })\n \n if (pageContext.selectedElements && pageContext.selectedElements.length > 0) {\n log.debug('Selected elements details', { \n elements: pageContext.selectedElements.map(el => ({\n filePath: el.filePath,\n line: el.line,\n text: el.innerText?.substring(0, 50)\n }))\n })\n }\n \n res.writeHead(200)\n res.end(JSON.stringify({ success: true }))\n ctx.end(200)\n } catch (e) {\n log.debug('Invalid JSON in request body', { error: e })\n res.writeHead(400)\n res.end(JSON.stringify({ error: 'Invalid JSON' }))\n ctx.end(400)\n }\n })\n return\n }\n\n res.writeHead(405)\n res.end(JSON.stringify({ error: 'Method not allowed' }))\n ctx.end(405)\n }\n\n return {\n name: 'vite-plugin-opencode',\n\n async configureServer(server: ViteDevServer) {\n if (!config.enabled) {\n log.debug('Plugin disabled, skipping configuration')\n return\n }\n\n const timer = log.timer('configureServer')\n\n server.middlewares.use(WIDGET_SCRIPT_PATH, async (_req, res) => {\n const ctx = new RequestContext('GET', WIDGET_SCRIPT_PATH)\n const widgetPath = path.join(__dirname, 'client.js')\n \n if (fs.existsSync(widgetPath)) {\n res.setHeader('Content-Type', 'application/javascript')\n res.setHeader('Access-Control-Allow-Origin', '*')\n fs.createReadStream(widgetPath).pipe(res)\n ctx.end(200)\n } else {\n res.writeHead(404)\n res.end('Widget script not found')\n ctx.end(404)\n }\n })\n\n server.middlewares.use(CONTEXT_API_PATH, async (req, res) => {\n handleContextRequest(req as http.IncomingMessage, res)\n })\n\n server.middlewares.use(START_API_PATH, async (_req, res) => {\n const ctx = new RequestContext('GET', START_API_PATH)\n \n res.setHeader('Content-Type', 'application/json')\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.writeHead(200)\n res.end(JSON.stringify({ success: true, sessionUrl }))\n ctx.end(200)\n })\n\n server.middlewares.use(SSE_EVENTS_PATH, async (req, res) => {\n const ctx = new RequestContext('GET', SSE_EVENTS_PATH)\n\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n\n sseClients.add(res)\n log.debug('SSE client connected', { totalClients: sseClients.size })\n\n res.write(`data: ${JSON.stringify({ type: 'CONNECTED' })}\\n\\n`)\n\n req.on('close', () => {\n sseClients.delete(res)\n log.debug('SSE client disconnected', { totalClients: sseClients.size })\n })\n \n ctx.end(200)\n })\n\n server.middlewares.use(SESSIONS_API_PATH, async (req, res) => {\n const ctx = new RequestContext(req.method || 'GET', SESSIONS_API_PATH)\n \n res.setHeader('Content-Type', 'application/json')\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type')\n\n if (req.method === 'OPTIONS') {\n res.writeHead(200)\n res.end()\n ctx.end(200)\n return\n }\n\n try {\n if (req.method === 'GET') {\n ctx.checkpoint('Fetching sessions')\n const sessions = await getSessions()\n res.writeHead(200)\n res.end(JSON.stringify(sessions))\n ctx.end(200)\n } else if (req.method === 'POST') {\n ctx.checkpoint('Creating session')\n const newSession = await createSession()\n res.writeHead(200)\n res.end(JSON.stringify(newSession))\n ctx.end(200)\n } else if (req.method === 'DELETE') {\n const url = new URL(req.url || '', `http://${req.headers.host}`)\n const sessionId = url.searchParams.get('id')\n \n if (!sessionId) {\n res.writeHead(400)\n res.end(JSON.stringify({ error: 'Session ID is required' }))\n ctx.end(400)\n return\n }\n \n ctx.checkpoint(`Deleting session: ${sessionId}`)\n await deleteSession(sessionId)\n res.writeHead(200)\n res.end(JSON.stringify({ success: true }))\n ctx.end(200)\n } else {\n res.writeHead(405)\n res.end(JSON.stringify({ error: 'Method not allowed' }))\n ctx.end(405)\n }\n } catch (e) {\n log.error('Session API error', { error: e, method: req.method })\n res.writeHead(500)\n res.end(JSON.stringify({ error: String(e) }))\n ctx.error(e)\n }\n })\n\n server.httpServer?.on('listening', async () => {\n log.debug('Vite server listening event fired')\n \n const address = server.httpServer?.address()\n let vitePort: number\n let viteHost: string\n \n if (address && typeof address === 'object') {\n vitePort = address.port\n const addr = address.address\n if (addr === '::' || addr === '::1' || addr === '0.0.0.0' || !addr) {\n viteHost = 'localhost'\n } else {\n viteHost = addr\n }\n } else {\n const host = server.config.server.host\n vitePort = server.config.server.port || 5173\n viteHost = typeof host === 'string' && host !== '0.0.0.0' && host !== '::' && host !== '::1' ? host : 'localhost'\n }\n \n const viteOrigin = `http://${viteHost}:${vitePort}`\n const contextApiUrl = `http://${viteHost}:${vitePort}${CONTEXT_API_PATH}`\n\n log.debug('Vite server ready', { vitePort, viteHost, viteOrigin, contextApiUrl })\n\n try {\n await startServices([viteOrigin], contextApiUrl)\n } catch (e) {\n log.error('Failed to start services', { error: e })\n }\n })\n \n server.httpServer?.on('close', () => {\n log.debug('HTTP server closing')\n stopServices()\n })\n \n const cleanup = async () => {\n log.debug('Process cleanup triggered')\n await stopServices()\n process.exit(0)\n }\n \n process.on('SIGINT', cleanup)\n process.on('SIGTERM', cleanup)\n\n timer.end('✓ Server configured')\n },\n\n transformIndexHtml(html) {\n const timer = log.timer('transformIndexHtml')\n \n const widget = injectWidget({\n webUrl: `http://${config.hostname}:${actualWebPort}`,\n serverUrl: `http://${config.hostname}:${actualWebPort}`,\n position: config.position,\n theme: config.theme,\n open: config.open,\n autoReload: config.autoReload,\n cwd: process.cwd(),\n sessionUrl: sessionUrl || undefined,\n hotkey: config.hotkey,\n })\n \n timer.end()\n return html.replace('</body>', `${widget}</body>`)\n },\n }\n}\n"]}
|
package/dist/vite/injector.d.ts
DELETED
package/dist/vite/injector.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { WIDGET_SCRIPT_PATH, CONFIG_DATA_ATTR } from '../constants.js';
|
|
2
|
-
export function injectWidget(options) {
|
|
3
|
-
const configBase64 = Buffer.from(JSON.stringify(options)).toString('base64');
|
|
4
|
-
return `<script src="${WIDGET_SCRIPT_PATH}" ${CONFIG_DATA_ATTR}="${configBase64}"></script>`;
|
|
5
|
-
}
|
|
6
|
-
//# sourceMappingURL=injector.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"injector.js","sourceRoot":"","sources":["../../src/vite/injector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAEtE,MAAM,UAAU,YAAY,CAAC,OAAsB;IACjD,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC5E,OAAO,gBAAgB,kBAAkB,KAAK,gBAAgB,KAAK,YAAY,aAAa,CAAA;AAC9F,CAAC","sourcesContent":["import { WidgetOptions } from '../types.js'\nimport { WIDGET_SCRIPT_PATH, CONFIG_DATA_ATTR } from '../constants.js'\n\nexport function injectWidget(options: WidgetOptions): string {\n const configBase64 = Buffer.from(JSON.stringify(options)).toString('base64')\n return `<script src=\"${WIDGET_SCRIPT_PATH}\" ${CONFIG_DATA_ATTR}=\"${configBase64}\"></script>`\n}\n"]}
|