vite-plugin-opencode-assistant 1.0.0

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/dist/index.js ADDED
@@ -0,0 +1,448 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import http from 'http';
4
+ import { startOpenCodeWeb } from './web';
5
+ import { injectWidget } from './injector';
6
+ import { checkOpenCodeInstalled, findAvailablePort, killProcessOnPort, checkOpenCodeProcess } from './utils';
7
+ import { DEFAULT_CONFIG, DEFAULT_RETRIES, RETRY_DELAY, PROCESS_KILL_DELAY, LOG_PREFIX, WIDGET_SCRIPT_PATH, CONTEXT_API_PATH, START_API_PATH, SESSIONS_API_PATH, } from './constants';
8
+ /**
9
+ * OpenCode Vite 插件
10
+ * @param options - 插件配置选项
11
+ * @returns Vite 插件实例
12
+ * @example
13
+ * ```ts
14
+ * // vite.config.ts
15
+ * import opencode from 'vite-plugin-opencode'
16
+ *
17
+ * export default {
18
+ * plugins: [
19
+ * opencode({
20
+ * webPort: 4097,
21
+ * position: 'bottom-right',
22
+ * theme: 'auto'
23
+ * })
24
+ * ]
25
+ * }
26
+ * ```
27
+ */
28
+ export default function opencodePlugin(options = {}) {
29
+ let webProcess = null;
30
+ let sessionUrl = null;
31
+ let actualWebPort = DEFAULT_CONFIG.webPort;
32
+ let isStarted = false;
33
+ let startPromise = null;
34
+ let pageContext = { url: '', title: '' };
35
+ const config = { ...DEFAULT_CONFIG, ...options };
36
+ /**
37
+ * 输出日志(仅在 verbose 模式下)
38
+ */
39
+ function log(message, ...args) {
40
+ if (config.verbose) {
41
+ console.log(`${LOG_PREFIX} ${message}`, ...args);
42
+ }
43
+ }
44
+ /**
45
+ * 输出错误日志
46
+ */
47
+ function logError(message, ...args) {
48
+ console.error(`${LOG_PREFIX} ${message}`, ...args);
49
+ }
50
+ /**
51
+ * Base64 编码字符串
52
+ */
53
+ function base64Encode(str) {
54
+ return Buffer.from(str).toString('base64');
55
+ }
56
+ /**
57
+ * 延迟执行
58
+ */
59
+ function sleep(ms) {
60
+ return new Promise(resolve => setTimeout(resolve, ms));
61
+ }
62
+ /**
63
+ * 创建 HTTP 请求 Promise
64
+ */
65
+ function createHttpRequest(options, body) {
66
+ return new Promise((resolve, reject) => {
67
+ const req = http.request(options, (res) => {
68
+ let data = '';
69
+ res.on('data', chunk => data += chunk);
70
+ res.on('end', () => {
71
+ try {
72
+ resolve(JSON.parse(data));
73
+ }
74
+ catch {
75
+ reject(new Error(`JSON parse error: ${data.substring(0, 100)}`));
76
+ }
77
+ });
78
+ });
79
+ req.on('error', reject);
80
+ if (body)
81
+ req.write(body);
82
+ req.end();
83
+ });
84
+ }
85
+ /**
86
+ * 获取会话列表
87
+ */
88
+ async function getSessions(retries = DEFAULT_RETRIES) {
89
+ let lastError = null;
90
+ for (let i = 0; i < retries; i++) {
91
+ try {
92
+ return await createHttpRequest({
93
+ hostname: config.hostname,
94
+ port: actualWebPort,
95
+ path: '/session',
96
+ });
97
+ }
98
+ catch (e) {
99
+ lastError = e instanceof Error ? e : new Error(String(e));
100
+ if (i < retries - 1)
101
+ await sleep(RETRY_DELAY);
102
+ }
103
+ }
104
+ throw lastError;
105
+ }
106
+ /**
107
+ * 创建新会话
108
+ */
109
+ async function createSession(retries = DEFAULT_RETRIES) {
110
+ let lastError = null;
111
+ for (let i = 0; i < retries; i++) {
112
+ try {
113
+ return await createHttpRequest({
114
+ hostname: config.hostname,
115
+ port: actualWebPort,
116
+ path: '/session',
117
+ method: 'POST',
118
+ });
119
+ }
120
+ catch (e) {
121
+ lastError = e instanceof Error ? e : new Error(String(e));
122
+ if (i < retries - 1)
123
+ await sleep(RETRY_DELAY);
124
+ }
125
+ }
126
+ throw lastError;
127
+ }
128
+ /**
129
+ * 删除会话
130
+ */
131
+ async function deleteSession(sessionId, retries = DEFAULT_RETRIES) {
132
+ let lastError = null;
133
+ for (let i = 0; i < retries; i++) {
134
+ try {
135
+ await createHttpRequest({
136
+ hostname: config.hostname,
137
+ port: actualWebPort,
138
+ path: `/session/${sessionId}`,
139
+ method: 'DELETE',
140
+ });
141
+ return;
142
+ }
143
+ catch (e) {
144
+ lastError = e instanceof Error ? e : new Error(String(e));
145
+ if (i < retries - 1)
146
+ await sleep(RETRY_DELAY);
147
+ }
148
+ }
149
+ throw lastError;
150
+ }
151
+ /**
152
+ * 获取或创建会话
153
+ */
154
+ async function getOrCreateSession() {
155
+ const projectDir = process.cwd();
156
+ log('Getting sessions...');
157
+ const sessions = await getSessions();
158
+ log(`Found ${sessions.length} sessions`);
159
+ const matchingSession = sessions.find(s => s.directory === projectDir);
160
+ if (matchingSession) {
161
+ return `http://${config.hostname}:${actualWebPort}/${base64Encode(projectDir)}/session/${matchingSession.id}`;
162
+ }
163
+ log('Creating new session...');
164
+ const newSession = await createSession();
165
+ return `http://${config.hostname}:${actualWebPort}/${base64Encode(projectDir)}/session/${newSession.id}`;
166
+ }
167
+ /**
168
+ * 设置 OpenCode 插件
169
+ */
170
+ function setupOpenCodePlugin() {
171
+ const projectDir = process.cwd();
172
+ const cacheDir = path.join(projectDir, 'node_modules', '.cache', 'opencode');
173
+ const pluginsDir = path.join(cacheDir, 'plugins');
174
+ if (!fs.existsSync(pluginsDir)) {
175
+ fs.mkdirSync(pluginsDir, { recursive: true });
176
+ }
177
+ const pluginSourcePath = path.join(__dirname, 'plugins', 'page-context.js');
178
+ const pluginTargetPath = path.join(pluginsDir, 'page-context.js');
179
+ if (fs.existsSync(pluginSourcePath)) {
180
+ fs.copyFileSync(pluginSourcePath, pluginTargetPath);
181
+ log(`Plugin installed to ${pluginTargetPath}`);
182
+ }
183
+ else {
184
+ console.warn(`${LOG_PREFIX} Plugin source not found: ${pluginSourcePath}`);
185
+ }
186
+ return cacheDir;
187
+ }
188
+ /**
189
+ * 启动服务
190
+ */
191
+ async function startServices(corsOrigins, contextApiUrl) {
192
+ if (isStarted)
193
+ return;
194
+ if (startPromise)
195
+ return startPromise;
196
+ startPromise = (async () => {
197
+ log('Starting OpenCode services...');
198
+ if (!await checkOpenCodeInstalled()) {
199
+ logError(`OpenCode is not installed!
200
+
201
+ Please install OpenCode first:
202
+
203
+ # Using Homebrew (macOS)
204
+ brew install opencode-ai/tap/opencode
205
+
206
+ # Or using the install script
207
+ curl -fsSL https://opencode.ai/install | bash
208
+ `);
209
+ return;
210
+ }
211
+ actualWebPort = await findAvailablePort(config.webPort, config.hostname);
212
+ if (actualWebPort !== config.webPort) {
213
+ log(`Port ${config.webPort} is in use, using ${actualWebPort} instead`);
214
+ }
215
+ const existingProcess = await checkOpenCodeProcess(actualWebPort);
216
+ if (existingProcess) {
217
+ log(`Found existing OpenCode process on port ${actualWebPort}`);
218
+ }
219
+ else {
220
+ const killed = await killProcessOnPort(actualWebPort, config.hostname);
221
+ if (killed) {
222
+ log(`Killed stale process on port ${actualWebPort}`);
223
+ await sleep(PROCESS_KILL_DELAY);
224
+ }
225
+ }
226
+ const configDir = setupOpenCodePlugin();
227
+ if (!existingProcess) {
228
+ webProcess = await startOpenCodeWeb({
229
+ port: actualWebPort,
230
+ hostname: config.hostname,
231
+ serverUrl: '',
232
+ cwd: process.cwd(),
233
+ configDir,
234
+ corsOrigins,
235
+ contextApiUrl,
236
+ });
237
+ log(`OpenCode Web started at http://${config.hostname}:${actualWebPort}`);
238
+ }
239
+ try {
240
+ sessionUrl = await getOrCreateSession();
241
+ log(`Session URL: ${sessionUrl}`);
242
+ }
243
+ catch (e) {
244
+ console.warn(`${LOG_PREFIX} Failed to get/create session:`, e);
245
+ }
246
+ isStarted = true;
247
+ })();
248
+ return startPromise;
249
+ }
250
+ /**
251
+ * 停止服务
252
+ */
253
+ async function stopServices() {
254
+ log('Stopping OpenCode services...');
255
+ if (webProcess) {
256
+ webProcess.kill('SIGTERM');
257
+ await new Promise(resolve => {
258
+ webProcess?.on('exit', () => resolve());
259
+ setTimeout(() => {
260
+ webProcess?.kill('SIGKILL');
261
+ resolve();
262
+ }, 3000);
263
+ });
264
+ webProcess = null;
265
+ }
266
+ if (isStarted) {
267
+ await killProcessOnPort(actualWebPort, config.hostname);
268
+ }
269
+ isStarted = false;
270
+ startPromise = null;
271
+ }
272
+ /**
273
+ * 处理上下文 API 请求
274
+ */
275
+ function handleContextRequest(req, res) {
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
+ return;
284
+ }
285
+ if (req.method === 'GET') {
286
+ res.writeHead(200);
287
+ res.end(JSON.stringify(pageContext));
288
+ return;
289
+ }
290
+ if (req.method === 'DELETE') {
291
+ pageContext.selectedElements = [];
292
+ log('Selected elements cleared');
293
+ res.writeHead(200);
294
+ res.end(JSON.stringify({ success: true }));
295
+ return;
296
+ }
297
+ if (req.method === 'POST') {
298
+ let body = '';
299
+ req.on('data', chunk => body += chunk);
300
+ req.on('end', () => {
301
+ try {
302
+ const data = JSON.parse(body);
303
+ pageContext = {
304
+ url: data.url || '',
305
+ title: data.title || '',
306
+ selectedElements: data.selectedElements || [],
307
+ };
308
+ log(`Context updated: ${pageContext.url}`, data.selectedElements?.length ? `elements: ${data.selectedElements.length}` : '');
309
+ res.writeHead(200);
310
+ res.end(JSON.stringify({ success: true }));
311
+ }
312
+ catch {
313
+ res.writeHead(400);
314
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
315
+ }
316
+ });
317
+ return;
318
+ }
319
+ res.writeHead(405);
320
+ res.end(JSON.stringify({ error: 'Method not allowed' }));
321
+ }
322
+ return {
323
+ name: 'vite-plugin-opencode',
324
+ async configureServer(server) {
325
+ if (!config.enabled)
326
+ return;
327
+ const vitePort = server.config.server.port || 5173;
328
+ const viteHost = server.config.server.host || 'localhost';
329
+ const viteOrigin = `http://${viteHost}:${vitePort}`;
330
+ const contextApiUrl = `http://${viteHost}:${vitePort}${CONTEXT_API_PATH}`;
331
+ if (!config.lazy) {
332
+ await startServices([viteOrigin], contextApiUrl);
333
+ }
334
+ server.middlewares.use(WIDGET_SCRIPT_PATH, async (_req, res) => {
335
+ if (config.lazy && !isStarted) {
336
+ await startServices([viteOrigin], contextApiUrl);
337
+ }
338
+ const widgetPath = path.join(__dirname, 'client.js');
339
+ if (fs.existsSync(widgetPath)) {
340
+ res.setHeader('Content-Type', 'application/javascript');
341
+ res.setHeader('Access-Control-Allow-Origin', '*');
342
+ fs.createReadStream(widgetPath).pipe(res);
343
+ }
344
+ else {
345
+ res.writeHead(404);
346
+ res.end('Widget script not found');
347
+ }
348
+ });
349
+ server.middlewares.use(CONTEXT_API_PATH, async (req, res) => {
350
+ if (config.lazy && !isStarted) {
351
+ await startServices([viteOrigin], contextApiUrl);
352
+ }
353
+ handleContextRequest(req, res);
354
+ });
355
+ server.middlewares.use(START_API_PATH, async (_req, res) => {
356
+ res.setHeader('Content-Type', 'application/json');
357
+ res.setHeader('Access-Control-Allow-Origin', '*');
358
+ if (config.lazy && !isStarted) {
359
+ try {
360
+ await startServices([viteOrigin], contextApiUrl);
361
+ res.writeHead(200);
362
+ res.end(JSON.stringify({ success: true, sessionUrl }));
363
+ }
364
+ catch (e) {
365
+ res.writeHead(500);
366
+ res.end(JSON.stringify({ error: String(e) }));
367
+ }
368
+ }
369
+ else {
370
+ res.writeHead(200);
371
+ res.end(JSON.stringify({ success: true, sessionUrl }));
372
+ }
373
+ });
374
+ server.middlewares.use(SESSIONS_API_PATH, async (req, res) => {
375
+ res.setHeader('Content-Type', 'application/json');
376
+ res.setHeader('Access-Control-Allow-Origin', '*');
377
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
378
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
379
+ if (req.method === 'OPTIONS') {
380
+ res.writeHead(200);
381
+ res.end();
382
+ return;
383
+ }
384
+ if (config.lazy && !isStarted) {
385
+ await startServices([viteOrigin], contextApiUrl);
386
+ }
387
+ try {
388
+ if (req.method === 'GET') {
389
+ const sessions = await getSessions();
390
+ res.writeHead(200);
391
+ res.end(JSON.stringify(sessions));
392
+ }
393
+ else if (req.method === 'POST') {
394
+ const newSession = await createSession();
395
+ res.writeHead(200);
396
+ res.end(JSON.stringify(newSession));
397
+ }
398
+ else if (req.method === 'DELETE') {
399
+ const url = new URL(req.url || '', `http://${req.headers.host}`);
400
+ const sessionId = url.searchParams.get('id');
401
+ if (!sessionId) {
402
+ res.writeHead(400);
403
+ res.end(JSON.stringify({ error: 'Session ID is required' }));
404
+ return;
405
+ }
406
+ await deleteSession(sessionId);
407
+ res.writeHead(200);
408
+ res.end(JSON.stringify({ success: true }));
409
+ }
410
+ else {
411
+ res.writeHead(405);
412
+ res.end(JSON.stringify({ error: 'Method not allowed' }));
413
+ }
414
+ }
415
+ catch (e) {
416
+ res.writeHead(500);
417
+ res.end(JSON.stringify({ error: String(e) }));
418
+ }
419
+ });
420
+ server.httpServer?.on('close', stopServices);
421
+ const cleanup = async () => {
422
+ await stopServices();
423
+ process.exit(0);
424
+ };
425
+ process.on('SIGINT', cleanup);
426
+ process.on('SIGTERM', cleanup);
427
+ process.on('exit', () => {
428
+ webProcess?.kill('SIGKILL');
429
+ });
430
+ },
431
+ transformIndexHtml(html) {
432
+ const widget = injectWidget({
433
+ webUrl: `http://${config.hostname}:${actualWebPort}`,
434
+ serverUrl: `http://${config.hostname}:${actualWebPort}`,
435
+ position: config.position,
436
+ theme: config.theme,
437
+ open: config.open,
438
+ autoReload: config.autoReload,
439
+ cwd: process.cwd(),
440
+ sessionUrl: sessionUrl || undefined,
441
+ lazy: config.lazy,
442
+ hotkey: config.hotkey,
443
+ });
444
+ return html.replace('</body>', `${widget}</body>`);
445
+ },
446
+ };
447
+ }
448
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBQ3ZCLE9BQU8sRUFBRSxNQUFNLElBQUksQ0FBQTtBQUNuQixPQUFPLElBQUksTUFBTSxNQUFNLENBQUE7QUFDdkIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sT0FBTyxDQUFBO0FBQ3hDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDekMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLGlCQUFpQixFQUFFLGlCQUFpQixFQUFFLG9CQUFvQixFQUFFLE1BQU0sU0FBUyxDQUFBO0FBRTVHLE9BQU8sRUFDTCxjQUFjLEVBQ2QsZUFBZSxFQUNmLFdBQVcsRUFDWCxrQkFBa0IsRUFDbEIsVUFBVSxFQUNWLGtCQUFrQixFQUNsQixnQkFBZ0IsRUFDaEIsY0FBYyxFQUNkLGlCQUFpQixHQUNsQixNQUFNLGFBQWEsQ0FBQTtBQUVwQjs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUNILE1BQU0sQ0FBQyxPQUFPLFVBQVUsY0FBYyxDQUFDLFVBQTJCLEVBQUU7SUFDbEUsSUFBSSxVQUFVLEdBQXdCLElBQUksQ0FBQTtJQUMxQyxJQUFJLFVBQVUsR0FBa0IsSUFBSSxDQUFBO0lBQ3BDLElBQUksYUFBYSxHQUFXLGNBQWMsQ0FBQyxPQUFPLENBQUE7SUFDbEQsSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFBO0lBQ3JCLElBQUksWUFBWSxHQUF5QixJQUFJLENBQUE7SUFDN0MsSUFBSSxXQUFXLEdBQWdCLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUE7SUFFckQsTUFBTSxNQUFNLEdBQUcsRUFBRSxHQUFHLGNBQWMsRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFBO0lBRWhEOztPQUVHO0lBQ0gsU0FBUyxHQUFHLENBQUMsT0FB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Q0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgUGx1Z2luLCBWaXRlRGV2U2VydmVyIH0gZnJvbSAndml0ZSdcbmltcG9ydCB7IHNwYXduLCBDaGlsZFByb2Nlc3MgfSBmcm9tICdjaGlsZF9wcm9jZXNzJ1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCdcbmltcG9ydCBmcyBmcm9tICdmcydcbmltcG9ydCBodHRwIGZyb20gJ2h0dHAnXG5pbXBvcnQgeyBzdGFydE9wZW5Db2RlV2ViIH0gZnJvbSAnLi93ZWInXG5pbXBvcnQgeyBpbmplY3RXaWRnZXQgfSBmcm9tICcuL2luamVjdG9yJ1xuaW1wb3J0IHsgY2hlY2tPcGVuQ29kZUluc3RhbGxlZCwgZmluZEF2YWlsYWJsZVBvcnQsIGtpbGxQcm9jZXNzT25Qb3J0LCBjaGVja09wZW5Db2RlUHJvY2VzcyB9IGZyb20gJy4vdXRpbHMnXG5pbXBvcnQgeyBPcGVuQ29kZU9wdGlvbnMsIFNlc3Npb25JbmZvLCBQYWdlQ29udGV4dCB9IGZyb20gJy4vdHlwZXMnXG5pbXBvcnQge1xuICBERUZBVUxUX0NPTkZJRyxcbiAgREVGQVVMVF9SRVRSSUVTLFxuICBSRVRSWV9ERUxBWSxcbiAgUFJPQ0VTU19LSUxMX0RFTEFZLFxuICBMT0dfUFJFRklYLFxuICBXSURHRVRfU0NSSVBUX1BBVEgsXG4gIENPTlRFWFRfQVBJX1BBVEgsXG4gIFNUQVJUX0FQSV9QQVRILFxuICBTRVNTSU9OU19BUElfUEFUSCxcbn0gZnJvbSAnLi9jb25zdGFudHMnXG5cbi8qKlxuICogT3BlbkNvZGUgVml0ZSDmj5Lku7ZcbiAqIEBwYXJhbSBvcHRpb25zIC0g5o+S5Lu26YWN572u6YCJ6aG5XG4gKiBAcmV0dXJucyBWaXRlIOaPkuS7tuWunuS+i1xuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiAvLyB2aXRlLmNvbmZpZy50c1xuICogaW1wb3J0IG9wZW5jb2RlIGZyb20gJ3ZpdGUtcGx1Z2luLW9wZW5jb2RlJ1xuICpcbiAqIGV4cG9ydCBkZWZhdWx0IHtcbiAqICAgcGx1Z2luczogW1xuICogICAgIG9wZW5jb2RlKHtcbiAqICAgICAgIHdlYlBvcnQ6IDQwOTcsXG4gKiAgICAgICBwb3NpdGlvbjogJ2JvdHRvbS1yaWdodCcsXG4gKiAgICAgICB0aGVtZTogJ2F1dG8nXG4gKiAgICAgfSlcbiAqICAgXVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIG9wZW5jb2RlUGx1Z2luKG9wdGlvbnM6IE9wZW5Db2RlT3B0aW9ucyA9IHt9KTogUGx1Z2luIHtcbiAgbGV0IHdlYlByb2Nlc3M6IENoaWxkUHJvY2VzcyB8IG51bGwgPSBudWxsXG4gIGxldCBzZXNzaW9uVXJsOiBzdHJpbmcgfCBudWxsID0gbnVsbFxuICBsZXQgYWN0dWFsV2ViUG9ydDogbnVtYmVyID0gREVGQVVMVF9DT05GSUcud2ViUG9ydFxuICBsZXQgaXNTdGFydGVkID0gZmFsc2VcbiAgbGV0IHN0YXJ0UHJvbWlzZTogUHJvbWlzZTx2b2lkPiB8IG51bGwgPSBudWxsXG4gIGxldCBwYWdlQ29udGV4dDogUGFnZUNvbnRleHQgPSB7IHVybDogJycsIHRpdGxlOiAnJyB9XG5cbiAgY29uc3QgY29uZmlnID0geyAuLi5ERUZBVUxUX0NPTkZJRywgLi4ub3B0aW9ucyB9XG5cbiAgLyoqXG4gICAqIOi+k+WHuuaXpeW/l++8iOS7heWcqCB2ZXJib3NlIOaooeW8j+S4i++8iVxuICAgKi9cbiAgZnVuY3Rpb24gbG9nKG1lc3NhZ2U6IHN0cmluZywgLi4uYXJnczogdW5rbm93bltdKTogdm9pZCB7XG4gICAgaWYgKGNvbmZpZy52ZXJib3NlKSB7XG4gICAgICBjb25zb2xlLmxvZyhgJHtMT0dfUFJFRklYfSAke21lc3NhZ2V9YCwgLi4uYXJncylcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog6L6T5Ye66ZSZ6K+v5pel5b+XXG4gICAqL1xuICBmdW5jdGlvbiBsb2dFcnJvcihtZXNzYWdlOiBzdHJpbmcsIC4uLmFyZ3M6IHVua25vd25bXSk6IHZvaWQge1xuICAgIGNvbnNvbGUuZXJyb3IoYCR7TE9HX1BSRUZJWH0gJHttZXNzYWdlfWAsIC4uLmFyZ3MpXG4gIH1cblxuICAvKipcbiAgICogQmFzZTY0IOe8lueggeWtl+espuS4slxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZTY0RW5jb2RlKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oc3RyKS50b1N0cmluZygnYmFzZTY0JylcbiAgfVxuXG4gIC8qKlxuICAgKiDlu7bov5/miafooYxcbiAgICovXG4gIGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSlcbiAgfVxuXG4gIC8qKlxuICAgKiDliJvlu7ogSFRUUCDor7fmsYIgUHJvbWlzZVxuICAgKi9cbiAgZnVuY3Rpb24gY3JlYXRlSHR0cFJlcXVlc3Q8VD4ob3B0aW9uczogaHR0cC5SZXF1ZXN0T3B0aW9ucywgYm9keT86IHN0cmluZyk6IFByb21pc2U8VD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXEgPSBodHRwLnJlcXVlc3Qob3B0aW9ucywgKHJlcykgPT4ge1xuICAgICAgICBsZXQgZGF0YSA9ICcnXG4gICAgICAgIHJlcy5vbignZGF0YScsIGNodW5rID0+IGRhdGEgKz0gY2h1bmspXG4gICAgICAgIHJlcy5vbignZW5kJywgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXNvbHZlKEpTT04ucGFyc2UoZGF0YSkpXG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBKU09OIHBhcnNlIGVycm9yOiAke2RhdGEuc3Vic3RyaW5nKDAsIDEwMCl9YCkpXG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgfSlcbiAgICAgIHJlcS5vbignZXJyb3InLCByZWplY3QpXG4gICAgICBpZiAoYm9keSkgcmVxLndyaXRlKGJvZHkpXG4gICAgICByZXEuZW5kKClcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIOiOt+WPluS8muivneWIl+ihqFxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gZ2V0U2Vzc2lvbnMocmV0cmllcyA9IERFRkFVTFRfUkVUUklFUyk6IFByb21pc2U8U2Vzc2lvbkluZm9bXT4ge1xuICAgIGxldCBsYXN0RXJyb3I6IEVycm9yIHwgbnVsbCA9IG51bGxcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmV0cmllczsgaSsrKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgY3JlYXRlSHR0cFJlcXVlc3Q8U2Vzc2lvbkluZm9bXT4oe1xuICAgICAgICAgIGhvc3RuYW1lOiBjb25maWcuaG9zdG5hbWUsXG4gICAgICAgICAgcG9ydDogYWN0dWFsV2ViUG9ydCxcbiAgICAgICAgICBwYXRoOiAnL3Nlc3Npb24nLFxuICAgICAgICB9KVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBsYXN0RXJyb3IgPSBlIGluc3RhbmNlb2YgRXJyb3IgPyBlIDogbmV3IEVycm9yKFN0cmluZyhlKSlcbiAgICAgICAgaWYgKGkgPCByZXRyaWVzIC0gMSkgYXdhaXQgc2xlZXAoUkVUUllfREVMQVkpXG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbGFzdEVycm9yXG4gIH1cblxuICAvKipcbiAgICog5Yib5bu65paw5Lya6K+dXG4gICAqL1xuICBhc3luYyBmdW5jdGlvbiBjcmVhdGVTZXNzaW9uKHJldHJpZXMgPSBERUZBVUxUX1JFVFJJRVMpOiBQcm9taXNlPFNlc3Npb25JbmZvPiB7XG4gICAgbGV0IGxhc3RFcnJvcjogRXJyb3IgfCBudWxsID0gbnVsbFxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXRyaWVzOyBpKyspIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBjcmVhdGVIdHRwUmVxdWVzdDxTZXNzaW9uSW5mbz4oe1xuICAgICAgICAgIGhvc3RuYW1lOiBjb25maWcuaG9zdG5hbWUsXG4gICAgICAgICAgcG9ydDogYWN0dWFsV2ViUG9ydCxcbiAgICAgICAgICBwYXRoOiAnL3Nlc3Npb24nLFxuICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICB9KVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBsYXN0RXJyb3IgPSBlIGluc3RhbmNlb2YgRXJyb3IgPyBlIDogbmV3IEVycm9yKFN0cmluZyhlKSlcbiAgICAgICAgaWYgKGkgPCByZXRyaWVzIC0gMSkgYXdhaXQgc2xlZXAoUkVUUllfREVMQVkpXG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbGFzdEVycm9yXG4gIH1cblxuICAvKipcbiAgICog5Yig6Zmk5Lya6K+dXG4gICAqL1xuICBhc3luYyBmdW5jdGlvbiBkZWxldGVTZXNzaW9uKHNlc3Npb25JZDogc3RyaW5nLCByZXRyaWVzID0gREVGQVVMVF9SRVRSSUVTKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IGxhc3RFcnJvcjogRXJyb3IgfCBudWxsID0gbnVsbFxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXRyaWVzOyBpKyspIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNyZWF0ZUh0dHBSZXF1ZXN0PHZvaWQ+KHtcbiAgICAgICAgICBob3N0bmFtZTogY29uZmlnLmhvc3RuYW1lLFxuICAgICAgICAgIHBvcnQ6IGFjdHVhbFdlYlBvcnQsXG4gICAgICAgICAgcGF0aDogYC9zZXNzaW9uLyR7c2Vzc2lvbklkfWAsXG4gICAgICAgICAgbWV0aG9kOiAnREVMRVRFJyxcbiAgICAgICAgfSlcbiAgICAgICAgcmV0dXJuXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGxhc3RFcnJvciA9IGUgaW5zdGFuY2VvZiBFcnJvciA/IGUgOiBuZXcgRXJyb3IoU3RyaW5nKGUpKVxuICAgICAgICBpZiAoaSA8IHJldHJpZXMgLSAxKSBhd2FpdCBzbGVlcChSRVRSWV9ERUxBWSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBsYXN0RXJyb3JcbiAgfVxuXG4gIC8qKlxuICAgKiDojrflj5bmiJbliJvlu7rkvJror51cbiAgICovXG4gIGFzeW5jIGZ1bmN0aW9uIGdldE9yQ3JlYXRlU2Vzc2lvbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHByb2plY3REaXIgPSBwcm9jZXNzLmN3ZCgpXG4gICAgbG9nKCdHZXR0aW5nIHNlc3Npb25zLi4uJylcbiAgICBjb25zdCBzZXNzaW9ucyA9IGF3YWl0IGdldFNlc3Npb25zKClcbiAgICBsb2coYEZvdW5kICR7c2Vzc2lvbnMubGVuZ3RofSBzZXNzaW9uc2ApXG5cbiAgICBjb25zdCBtYXRjaGluZ1Nlc3Npb24gPSBzZXNzaW9ucy5maW5kKHMgPT4gcy5kaXJlY3RvcnkgPT09IHByb2plY3REaXIpXG5cbiAgICBpZiAobWF0Y2hpbmdTZXNzaW9uKSB7XG4gICAgICByZXR1cm4gYGh0dHA6Ly8ke2NvbmZpZy5ob3N0bmFtZX06JHthY3R1YWxXZWJQb3J0fS8ke2Jhc2U2NEVuY29kZShwcm9qZWN0RGlyKX0vc2Vzc2lvbi8ke21hdGNoaW5nU2Vzc2lvbi5pZH1gXG4gICAgfVxuXG4gICAgbG9nKCdDcmVhdGluZyBuZXcgc2Vzc2lvbi4uLicpXG4gICAgY29uc3QgbmV3U2Vzc2lvbiA9IGF3YWl0IGNyZWF0ZVNlc3Npb24oKVxuICAgIHJldHVybiBgaHR0cDovLyR7Y29uZmlnLmhvc3RuYW1lfToke2FjdHVhbFdlYlBvcnR9LyR7YmFzZTY0RW5jb2RlKHByb2plY3REaXIpfS9zZXNzaW9uLyR7bmV3U2Vzc2lvbi5pZH1gXG4gIH1cblxuICAvKipcbiAgICog6K6+572uIE9wZW5Db2RlIOaPkuS7tlxuICAgKi9cbiAgZnVuY3Rpb24gc2V0dXBPcGVuQ29kZVBsdWdpbigpOiBzdHJpbmcge1xuICAgIGNvbnN0IHByb2plY3REaXIgPSBwcm9jZXNzLmN3ZCgpXG4gICAgY29uc3QgY2FjaGVEaXIgPSBwYXRoLmpvaW4ocHJvamVjdERpciwgJ25vZGVfbW9kdWxlcycsICcuY2FjaGUnLCAnb3BlbmNvZGUnKVxuICAgIGNvbnN0IHBsdWdpbnNEaXIgPSBwYXRoLmpvaW4oY2FjaGVEaXIsICdwbHVnaW5zJylcblxuICAgIGlmICghZnMuZXhpc3RzU3luYyhwbHVnaW5zRGlyKSkge1xuICAgICAgZnMubWtkaXJTeW5jKHBsdWdpbnNEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG4gICAgfVxuXG4gICAgY29uc3QgcGx1Z2luU291cmNlUGF0aCA9IHBhdGguam9pbihfX2Rpcm5hbWUsICdwbHVnaW5zJywgJ3BhZ2UtY29udGV4dC5qcycpXG4gICAgY29uc3QgcGx1Z2luVGFyZ2V0UGF0aCA9IHBhdGguam9pbihwbHVnaW5zRGlyLCAncGFnZS1jb250ZXh0LmpzJylcblxuICAgIGlmIChmcy5leGlzdHNTeW5jKHBsdWdpblNvdXJjZVBhdGgpKSB7XG4gICAgICBmcy5jb3B5RmlsZVN5bmMocGx1Z2luU291cmNlUGF0aCwgcGx1Z2luVGFyZ2V0UGF0aClcbiAgICAgIGxvZyhgUGx1Z2luIGluc3RhbGxlZCB0byAke3BsdWdpblRhcmdldFBhdGh9YClcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKGAke0xPR19QUkVGSVh9IFBsdWdpbiBzb3VyY2Ugbm90IGZvdW5kOiAke3BsdWdpblNvdXJjZVBhdGh9YClcbiAgICB9XG5cbiAgICByZXR1cm4gY2FjaGVEaXJcbiAgfVxuXG4gIC8qKlxuICAgKiDlkK/liqjmnI3liqFcbiAgICovXG4gIGFzeW5jIGZ1bmN0aW9uIHN0YXJ0U2VydmljZXMoY29yc09yaWdpbnM/OiBzdHJpbmdbXSwgY29udGV4dEFwaVVybD86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChpc1N0YXJ0ZWQpIHJldHVyblxuICAgIGlmIChzdGFydFByb21pc2UpIHJldHVybiBzdGFydFByb21pc2VcblxuICAgIHN0YXJ0UHJvbWlzZSA9IChhc3luYyAoKSA9PiB7XG4gICAgICBsb2coJ1N0YXJ0aW5nIE9wZW5Db2RlIHNlcnZpY2VzLi4uJylcblxuICAgICAgaWYgKCFhd2FpdCBjaGVja09wZW5Db2RlSW5zdGFsbGVkKCkpIHtcbiAgICAgICAgbG9nRXJyb3IoYE9wZW5Db2RlIGlzIG5vdCBpbnN0YWxsZWQhXG5cblBsZWFzZSBpbnN0YWxsIE9wZW5Db2RlIGZpcnN0OlxuXG4gICMgVXNpbmcgSG9tZWJyZXcgKG1hY09TKVxuICBicmV3IGluc3RhbGwgb3BlbmNvZGUtYWkvdGFwL29wZW5jb2RlXG5cbiAgIyBPciB1c2luZyB0aGUgaW5zdGFsbCBzY3JpcHRcbiAgY3VybCAtZnNTTCBodHRwczovL29wZW5jb2RlLmFpL2luc3RhbGwgfCBiYXNoXG4gICAgICAgIGApXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBhY3R1YWxXZWJQb3J0ID0gYXdhaXQgZmluZEF2YWlsYWJsZVBvcnQoY29uZmlnLndlYlBvcnQsIGNvbmZpZy5ob3N0bmFtZSlcbiAgICAgIGlmIChhY3R1YWxXZWJQb3J0ICE9PSBjb25maWcud2ViUG9ydCkge1xuICAgICAgICBsb2coYFBvcnQgJHtjb25maWcud2ViUG9ydH0gaXMgaW4gdXNlLCB1c2luZyAke2FjdHVhbFdlYlBvcnR9IGluc3RlYWRgKVxuICAgICAgfVxuXG4gICAgICBjb25zdCBleGlzdGluZ1Byb2Nlc3MgPSBhd2FpdCBjaGVja09wZW5Db2RlUHJvY2VzcyhhY3R1YWxXZWJQb3J0KVxuICAgICAgaWYgKGV4aXN0aW5nUHJvY2Vzcykge1xuICAgICAgICBsb2coYEZvdW5kIGV4aXN0aW5nIE9wZW5Db2RlIHByb2Nlc3Mgb24gcG9ydCAke2FjdHVhbFdlYlBvcnR9YClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGtpbGxlZCA9IGF3YWl0IGtpbGxQcm9jZXNzT25Qb3J0KGFjdHVhbFdlYlBvcnQsIGNvbmZpZy5ob3N0bmFtZSlcbiAgICAgICAgaWYgKGtpbGxlZCkge1xuICAgICAgICAgIGxvZyhgS2lsbGVkIHN0YWxlIHByb2Nlc3Mgb24gcG9ydCAke2FjdHVhbFdlYlBvcnR9YClcbiAgICAgICAgICBhd2FpdCBzbGVlcChQUk9DRVNTX0tJTExfREVMQVkpXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgY29uZmlnRGlyID0gc2V0dXBPcGVuQ29kZVBsdWdpbigpXG5cbiAgICAgIGlmICghZXhpc3RpbmdQcm9jZXNzKSB7XG4gICAgICAgIHdlYlByb2Nlc3MgPSBhd2FpdCBzdGFydE9wZW5Db2RlV2ViKHtcbiAgICAgICAgICBwb3J0OiBhY3R1YWxXZWJQb3J0LFxuICAgICAgICAgIGhvc3RuYW1lOiBjb25maWcuaG9zdG5hbWUsXG4gICAgICAgICAgc2VydmVyVXJsOiAnJyxcbiAgICAgICAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgICAgICAgY29uZmlnRGlyLFxuICAgICAgICAgIGNvcnNPcmlnaW5zLFxuICAgICAgICAgIGNvbnRleHRBcGlVcmwsXG4gICAgICAgIH0pXG4gICAgICAgIGxvZyhgT3BlbkNvZGUgV2ViIHN0YXJ0ZWQgYXQgaHR0cDovLyR7Y29uZmlnLmhvc3RuYW1lfToke2FjdHVhbFdlYlBvcnR9YClcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgc2Vzc2lvblVybCA9IGF3YWl0IGdldE9yQ3JlYXRlU2Vzc2lvbigpXG4gICAgICAgIGxvZyhgU2Vzc2lvbiBVUkw6ICR7c2Vzc2lvblVybH1gKVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLndhcm4oYCR7TE9HX1BSRUZJWH0gRmFpbGVkIHRvIGdldC9jcmVhdGUgc2Vzc2lvbjpgLCBlKVxuICAgICAgfVxuXG4gICAgICBpc1N0YXJ0ZWQgPSB0cnVlXG4gICAgfSkoKVxuXG4gICAgcmV0dXJuIHN0YXJ0UHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIOWBnOatouacjeWKoVxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gc3RvcFNlcnZpY2VzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxvZygnU3RvcHBpbmcgT3BlbkNvZGUgc2VydmljZXMuLi4nKVxuICAgIFxuICAgIGlmICh3ZWJQcm9jZXNzKSB7XG4gICAgICB3ZWJQcm9jZXNzLmtpbGwoJ1NJR1RFUk0nKVxuICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4ocmVzb2x2ZSA9PiB7XG4gICAgICAgIHdlYlByb2Nlc3M/Lm9uKCdleGl0JywgKCkgPT4gcmVzb2x2ZSgpKVxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICB3ZWJQcm9jZXNzPy5raWxsKCdTSUdLSUxMJylcbiAgICAgICAgICByZXNvbHZlKClcbiAgICAgICAgfSwgMzAwMClcbiAgICAgIH0pXG4gICAgICB3ZWJQcm9jZXNzID0gbnVsbFxuICAgIH1cbiAgICBcbiAgICBpZiAoaXNTdGFydGVkKSB7XG4gICAgICBhd2FpdCBraWxsUHJvY2Vzc09uUG9ydChhY3R1YWxXZWJQb3J0LCBjb25maWcuaG9zdG5hbWUpXG4gICAgfVxuICAgIFxuICAgIGlzU3RhcnRlZCA9IGZhbHNlXG4gICAgc3RhcnRQcm9taXNlID0gbnVsbFxuICB9XG5cbiAgLyoqXG4gICAqIOWkhOeQhuS4iuS4i+aWhyBBUEkg6K+35rGCXG4gICAqL1xuICBmdW5jdGlvbiBoYW5kbGVDb250ZXh0UmVxdWVzdChyZXE6IGh0dHAuSW5jb21pbmdNZXNzYWdlLCByZXM6IGh0dHAuU2VydmVyUmVzcG9uc2UpOiB2b2lkIHtcbiAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpXG4gICAgcmVzLnNldEhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJywgJyonKVxuICAgIHJlcy5zZXRIZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUFsbG93LU1ldGhvZHMnLCAnR0VULCBQT1NULCBERUxFVEUsIE9QVElPTlMnKVxuICAgIHJlcy5zZXRIZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnMnLCAnQ29udGVudC1UeXBlJylcblxuICAgIGlmIChyZXEubWV0aG9kID09PSAnT1BUSU9OUycpIHtcbiAgICAgIHJlcy53cml0ZUhlYWQoMjAwKVxuICAgICAgcmVzLmVuZCgpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAocmVxLm1ldGhvZCA9PT0gJ0dFVCcpIHtcbiAgICAgIHJlcy53cml0ZUhlYWQoMjAwKVxuICAgICAgcmVzLmVuZChKU09OLnN0cmluZ2lmeShwYWdlQ29udGV4dCkpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAocmVxLm1ldGhvZCA9PT0gJ0RFTEVURScpIHtcbiAgICAgIHBhZ2VDb250ZXh0LnNlbGVjdGVkRWxlbWVudHMgPSBbXVxuICAgICAgbG9nKCdTZWxlY3RlZCBlbGVtZW50cyBjbGVhcmVkJylcbiAgICAgIHJlcy53cml0ZUhlYWQoMjAwKVxuICAgICAgcmVzLmVuZChKU09OLnN0cmluZ2lmeSh7IHN1Y2Nlc3M6IHRydWUgfSkpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAocmVxLm1ldGhvZCA9PT0gJ1BPU1QnKSB7XG4gICAgICBsZXQgYm9keSA9ICcnXG4gICAgICByZXEub24oJ2RhdGEnLCBjaHVuayA9PiBib2R5ICs9IGNodW5rKVxuICAgICAgcmVxLm9uKCdlbmQnLCAoKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZGF0YSA9IEpTT04ucGFyc2UoYm9keSlcbiAgICAgICAgICBwYWdlQ29udGV4dCA9IHtcbiAgICAgICAgICAgIHVybDogZGF0YS51cmwgfHwgJycsXG4gICAgICAgICAgICB0aXRsZTogZGF0YS50aXRsZSB8fCAnJyxcbiAgICAgICAgICAgIHNlbGVjdGVkRWxlbWVudHM6IGRhdGEuc2VsZWN0ZWRFbGVtZW50cyB8fCBbXSxcbiAgICAgICAgICB9XG4gICAgICAgICAgbG9nKGBDb250ZXh0IHVwZGF0ZWQ6ICR7cGFnZUNvbnRleHQudXJsfWAsIGRhdGEuc2VsZWN0ZWRFbGVtZW50cz8ubGVuZ3RoID8gYGVsZW1lbnRzOiAke2RhdGEuc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGh9YCA6ICcnKVxuICAgICAgICAgIHJlcy53cml0ZUhlYWQoMjAwKVxuICAgICAgICAgIHJlcy5lbmQoSlNPTi5zdHJpbmdpZnkoeyBzdWNjZXNzOiB0cnVlIH0pKVxuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICByZXMud3JpdGVIZWFkKDQwMClcbiAgICAgICAgICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KHsgZXJyb3I6ICdJbnZhbGlkIEpTT04nIH0pKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgcmVzLndyaXRlSGVhZCg0MDUpXG4gICAgcmVzLmVuZChKU09OLnN0cmluZ2lmeSh7IGVycm9yOiAnTWV0aG9kIG5vdCBhbGxvd2VkJyB9KSlcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLW9wZW5jb2RlJyxcblxuICAgIGFzeW5jIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXI6IFZpdGVEZXZTZXJ2ZXIpIHtcbiAgICAgIGlmICghY29uZmlnLmVuYWJsZWQpIHJldHVyblxuXG4gICAgICBjb25zdCB2aXRlUG9ydCA9IHNlcnZlci5jb25maWcuc2VydmVyLnBvcnQgfHwgNTE3M1xuICAgICAgY29uc3Qgdml0ZUhvc3QgPSBzZXJ2ZXIuY29uZmlnLnNlcnZlci5ob3N0IHx8ICdsb2NhbGhvc3QnXG4gICAgICBjb25zdCB2aXRlT3JpZ2luID0gYGh0dHA6Ly8ke3ZpdGVIb3N0fToke3ZpdGVQb3J0fWBcbiAgICAgIGNvbnN0IGNvbnRleHRBcGlVcmwgPSBgaHR0cDovLyR7dml0ZUhvc3R9OiR7dml0ZVBvcnR9JHtDT05URVhUX0FQSV9QQVRIfWBcblxuICAgICAgaWYgKCFjb25maWcubGF6eSkge1xuICAgICAgICBhd2FpdCBzdGFydFNlcnZpY2VzKFt2aXRlT3JpZ2luXSwgY29udGV4dEFwaVVybClcbiAgICAgIH1cblxuICAgICAgc2VydmVyLm1pZGRsZXdhcmVzLnVzZShXSURHRVRfU0NSSVBUX1BBVEgsIGFzeW5jIChfcmVxLCByZXMpID0+IHtcbiAgICAgICAgaWYgKGNvbmZpZy5sYXp5ICYmICFpc1N0YXJ0ZWQpIHtcbiAgICAgICAgICBhd2FpdCBzdGFydFNlcnZpY2VzKFt2aXRlT3JpZ2luXSwgY29udGV4dEFwaVVybClcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHdpZGdldFBhdGggPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAnY2xpZW50LmpzJylcbiAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMod2lkZ2V0UGF0aCkpIHtcbiAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vamF2YXNjcmlwdCcpXG4gICAgICAgICAgcmVzLnNldEhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJywgJyonKVxuICAgICAgICAgIGZzLmNyZWF0ZVJlYWRTdHJlYW0od2lkZ2V0UGF0aCkucGlwZShyZXMpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzLndyaXRlSGVhZCg0MDQpXG4gICAgICAgICAgcmVzLmVuZCgnV2lkZ2V0IHNjcmlwdCBub3QgZm91bmQnKVxuICAgICAgICB9XG4gICAgICB9KVxuXG4gICAgICBzZXJ2ZXIubWlkZGxld2FyZXMudXNlKENPTlRFWFRfQVBJX1BBVEgsIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgICAgICBpZiAoY29uZmlnLmxhenkgJiYgIWlzU3RhcnRlZCkge1xuICAgICAgICAgIGF3YWl0IHN0YXJ0U2VydmljZXMoW3ZpdGVPcmlnaW5dLCBjb250ZXh0QXBpVXJsKVxuICAgICAgICB9XG4gICAgICAgIGhhbmRsZUNvbnRleHRSZXF1ZXN0KHJlcSBhcyBodHRwLkluY29taW5nTWVzc2FnZSwgcmVzKVxuICAgICAgfSlcblxuICAgICAgc2VydmVyLm1pZGRsZXdhcmVzLnVzZShTVEFSVF9BUElfUEFUSCwgYXN5bmMgKF9yZXEsIHJlcykgPT4ge1xuICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpXG4gICAgICAgIHJlcy5zZXRIZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbicsICcqJylcblxuICAgICAgICBpZiAoY29uZmlnLmxhenkgJiYgIWlzU3RhcnRlZCkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBzdGFydFNlcnZpY2VzKFt2aXRlT3JpZ2luXSwgY29udGV4dEFwaVVybClcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoMjAwKVxuICAgICAgICAgICAgcmVzLmVuZChKU09OLnN0cmluZ2lmeSh7IHN1Y2Nlc3M6IHRydWUsIHNlc3Npb25VcmwgfSkpXG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmVzLndyaXRlSGVhZCg1MDApXG4gICAgICAgICAgICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KHsgZXJyb3I6IFN0cmluZyhlKSB9KSlcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzLndyaXRlSGVhZCgyMDApXG4gICAgICAgICAgcmVzLmVuZChKU09OLnN0cmluZ2lmeSh7IHN1Y2Nlc3M6IHRydWUsIHNlc3Npb25VcmwgfSkpXG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoU0VTU0lPTlNfQVBJX1BBVEgsIGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpXG4gICAgICAgIHJlcy5zZXRIZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbicsICcqJylcbiAgICAgICAgcmVzLnNldEhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcycsICdHRVQsIFBPU1QsIERFTEVURSwgT1BUSU9OUycpXG4gICAgICAgIHJlcy5zZXRIZWFkZXIoJ0FjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnMnLCAnQ29udGVudC1UeXBlJylcblxuICAgICAgICBpZiAocmVxLm1ldGhvZCA9PT0gJ09QVElPTlMnKSB7XG4gICAgICAgICAgcmVzLndyaXRlSGVhZCgyMDApXG4gICAgICAgICAgcmVzLmVuZCgpXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29uZmlnLmxhenkgJiYgIWlzU3RhcnRlZCkge1xuICAgICAgICAgIGF3YWl0IHN0YXJ0U2VydmljZXMoW3ZpdGVPcmlnaW5dLCBjb250ZXh0QXBpVXJsKVxuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpZiAocmVxLm1ldGhvZCA9PT0gJ0dFVCcpIHtcbiAgICAgICAgICAgIGNvbnN0IHNlc3Npb25zID0gYXdhaXQgZ2V0U2Vzc2lvbnMoKVxuICAgICAgICAgICAgcmVzLndyaXRlSGVhZCgyMDApXG4gICAgICAgICAgICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KHNlc3Npb25zKSlcbiAgICAgICAgICB9IGVsc2UgaWYgKHJlcS5tZXRob2QgPT09ICdQT1NUJykge1xuICAgICAgICAgICAgY29uc3QgbmV3U2Vzc2lvbiA9IGF3YWl0IGNyZWF0ZVNlc3Npb24oKVxuICAgICAgICAgICAgcmVzLndyaXRlSGVhZCgyMDApXG4gICAgICAgICAgICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KG5ld1Nlc3Npb24pKVxuICAgICAgICAgIH0gZWxzZSBpZiAocmVxLm1ldGhvZCA9PT0gJ0RFTEVURScpIHtcbiAgICAgICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxLnVybCB8fCAnJywgYGh0dHA6Ly8ke3JlcS5oZWFkZXJzLmhvc3R9YClcbiAgICAgICAgICAgIGNvbnN0IHNlc3Npb25JZCA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdpZCcpXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmICghc2Vzc2lvbklkKSB7XG4gICAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDAwKVxuICAgICAgICAgICAgICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KHsgZXJyb3I6ICdTZXNzaW9uIElEIGlzIHJlcXVpcmVkJyB9KSlcbiAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGF3YWl0IGRlbGV0ZVNlc3Npb24oc2Vzc2lvbklkKVxuICAgICAgICAgICAgcmVzLndyaXRlSGVhZCgyMDApXG4gICAgICAgICAgICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KHsgc3VjY2VzczogdHJ1ZSB9KSlcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzLndyaXRlSGVhZCg0MDUpXG4gICAgICAgICAgICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KHsgZXJyb3I6ICdNZXRob2Qgbm90IGFsbG93ZWQnIH0pKVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHJlcy53cml0ZUhlYWQoNTAwKVxuICAgICAgICAgIHJlcy5lbmQoSlNPTi5zdHJpbmdpZnkoeyBlcnJvcjogU3RyaW5nKGUpIH0pKVxuICAgICAgICB9XG4gICAgICB9KVxuXG4gICAgICBzZXJ2ZXIuaHR0cFNlcnZlcj8ub24oJ2Nsb3NlJywgc3RvcFNlcnZpY2VzKVxuICAgICAgXG4gICAgICBjb25zdCBjbGVhbnVwID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCBzdG9wU2VydmljZXMoKVxuICAgICAgICBwcm9jZXNzLmV4aXQoMClcbiAgICAgIH1cbiAgICAgIFxuICAgICAgcHJvY2Vzcy5vbignU0lHSU5UJywgY2xlYW51cClcbiAgICAgIHByb2Nlc3Mub24oJ1NJR1RFUk0nLCBjbGVhbnVwKVxuICAgICAgcHJvY2Vzcy5vbignZXhpdCcsICgpID0+IHtcbiAgICAgICAgd2ViUHJvY2Vzcz8ua2lsbCgnU0lHS0lMTCcpXG4gICAgICB9KVxuICAgIH0sXG5cbiAgICB0cmFuc2Zvcm1JbmRleEh0bWwoaHRtbCkge1xuICAgICAgY29uc3Qgd2lkZ2V0ID0gaW5qZWN0V2lkZ2V0KHtcbiAgICAgICAgd2ViVXJsOiBgaHR0cDovLyR7Y29uZmlnLmhvc3RuYW1lfToke2FjdHVhbFdlYlBvcnR9YCxcbiAgICAgICAgc2VydmVyVXJsOiBgaHR0cDovLyR7Y29uZmlnLmhvc3RuYW1lfToke2FjdHVhbFdlYlBvcnR9YCxcbiAgICAgICAgcG9zaXRpb246IGNvbmZpZy5wb3NpdGlvbixcbiAgICAgICAgdGhlbWU6IGNvbmZpZy50aGVtZSxcbiAgICAgICAgb3BlbjogY29uZmlnLm9wZW4sXG4gICAgICAgIGF1dG9SZWxvYWQ6IGNvbmZpZy5hdXRvUmVsb2FkLFxuICAgICAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgICAgIHNlc3Npb25Vcmw6IHNlc3Npb25VcmwgfHwgdW5kZWZpbmVkLFxuICAgICAgICBsYXp5OiBjb25maWcubGF6eSxcbiAgICAgICAgaG90a2V5OiBjb25maWcuaG90a2V5LFxuICAgICAgfSlcbiAgICAgIHJldHVybiBodG1sLnJlcGxhY2UoJzwvYm9keT4nLCBgJHt3aWRnZXR9PC9ib2R5PmApXG4gICAgfSxcbiAgfVxufVxuIl19
@@ -0,0 +1,20 @@
1
+ import { WidgetOptions } from './types';
2
+ /**
3
+ * 生成挂件注入脚本标签
4
+ * @param options - 挂件配置选项
5
+ * @returns HTML 脚本标签字符串
6
+ * @example
7
+ * ```ts
8
+ * const widget = injectWidget({
9
+ * webUrl: 'http://127.0.0.1:4097',
10
+ * serverUrl: 'http://127.0.0.1:4097',
11
+ * position: 'bottom-right',
12
+ * theme: 'auto',
13
+ * open: false,
14
+ * autoReload: true,
15
+ * cwd: process.cwd()
16
+ * })
17
+ * // 返回: '<script src="/__opencode_widget__.js" data-opencode-config="..."></script>'
18
+ * ```
19
+ */
20
+ export declare function injectWidget(options: WidgetOptions): string;
@@ -0,0 +1,24 @@
1
+ import { WIDGET_SCRIPT_PATH, CONFIG_DATA_ATTR } from './constants';
2
+ /**
3
+ * 生成挂件注入脚本标签
4
+ * @param options - 挂件配置选项
5
+ * @returns HTML 脚本标签字符串
6
+ * @example
7
+ * ```ts
8
+ * const widget = injectWidget({
9
+ * webUrl: 'http://127.0.0.1:4097',
10
+ * serverUrl: 'http://127.0.0.1:4097',
11
+ * position: 'bottom-right',
12
+ * theme: 'auto',
13
+ * open: false,
14
+ * autoReload: true,
15
+ * cwd: process.cwd()
16
+ * })
17
+ * // 返回: '<script src="/__opencode_widget__.js" data-opencode-config="..."></script>'
18
+ * ```
19
+ */
20
+ export function injectWidget(options) {
21
+ const configBase64 = Buffer.from(JSON.stringify(options)).toString('base64');
22
+ return `<script src="${WIDGET_SCRIPT_PATH}" ${CONFIG_DATA_ATTR}="${configBase64}"></script>`;
23
+ }
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5qZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5qZWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGdCQUFnQixFQUFFLE1BQU0sYUFBYSxDQUFBO0FBRWxFOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsT0FBc0I7SUFDakQsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQzVFLE9BQU8sZ0JBQWdCLGtCQUFrQixLQUFLLGdCQUFnQixLQUFLLFlBQVksYUFBYSxDQUFBO0FBQzlGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBXaWRnZXRPcHRpb25zIH0gZnJvbSAnLi90eXBlcydcbmltcG9ydCB7IFdJREdFVF9TQ1JJUFRfUEFUSCwgQ09ORklHX0RBVEFfQVRUUiB9IGZyb20gJy4vY29uc3RhbnRzJ1xuXG4vKipcbiAqIOeUn+aIkOaMguS7tuazqOWFpeiEmuacrOagh+etvlxuICogQHBhcmFtIG9wdGlvbnMgLSDmjILku7bphY3nva7pgInpoblcbiAqIEByZXR1cm5zIEhUTUwg6ISa5pys5qCH562+5a2X56ym5LiyXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIGNvbnN0IHdpZGdldCA9IGluamVjdFdpZGdldCh7XG4gKiAgIHdlYlVybDogJ2h0dHA6Ly8xMjcuMC4wLjE6NDA5NycsXG4gKiAgIHNlcnZlclVybDogJ2h0dHA6Ly8xMjcuMC4wLjE6NDA5NycsXG4gKiAgIHBvc2l0aW9uOiAnYm90dG9tLXJpZ2h0JyxcbiAqICAgdGhlbWU6ICdhdXRvJyxcbiAqICAgb3BlbjogZmFsc2UsXG4gKiAgIGF1dG9SZWxvYWQ6IHRydWUsXG4gKiAgIGN3ZDogcHJvY2Vzcy5jd2QoKVxuICogfSlcbiAqIC8vIOi/lOWbnjogJzxzY3JpcHQgc3JjPVwiL19fb3BlbmNvZGVfd2lkZ2V0X18uanNcIiBkYXRhLW9wZW5jb2RlLWNvbmZpZz1cIi4uLlwiPjwvc2NyaXB0PidcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5qZWN0V2lkZ2V0KG9wdGlvbnM6IFdpZGdldE9wdGlvbnMpOiBzdHJpbmcge1xuICBjb25zdCBjb25maWdCYXNlNjQgPSBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShvcHRpb25zKSkudG9TdHJpbmcoJ2Jhc2U2NCcpXG4gIHJldHVybiBgPHNjcmlwdCBzcmM9XCIke1dJREdFVF9TQ1JJUFRfUEFUSH1cIiAke0NPTkZJR19EQVRBX0FUVFJ9PVwiJHtjb25maWdCYXNlNjR9XCI+PC9zY3JpcHQ+YFxufVxuIl19
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @fileoverview OpenCode 页面上下文插件
3
+ * @description 用于将页面上下文信息注入到 AI 对话中
4
+ */
5
+ import type { Plugin } from "@opencode-ai/plugin";
6
+ /**
7
+ * OpenCode 页面上下文插件
8
+ * @returns 插件钩子
9
+ * @example
10
+ * ```ts
11
+ * // 在 opencode 配置中使用
12
+ * import { PageContextPlugin } from './plugins/page-context'
13
+ *
14
+ * export default {
15
+ * plugins: [PageContextPlugin]
16
+ * }
17
+ * ```
18
+ */
19
+ export declare const PageContextPlugin: Plugin;
20
+ export default PageContextPlugin;