vite-plugin-opencode-assistant 1.0.1 → 1.0.3

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.
@@ -0,0 +1,206 @@
1
+ import http from 'http';
2
+ import { spawn } from 'child_process';
3
+ import net from 'net';
4
+ import { DEFAULT_HOSTNAME, SERVER_CHECK_INTERVAL, MAX_PORT_TRIES, } from '../constants.js';
5
+ import { createLogger, PerformanceTimer } from '../logger.js';
6
+ const log = createLogger('Utils');
7
+ export function waitForServer(url, timeout = 10000) {
8
+ const timer = new PerformanceTimer('waitForServer', { url, timeout });
9
+ return new Promise((resolve, reject) => {
10
+ const startTime = Date.now();
11
+ let attempts = 0;
12
+ const check = () => {
13
+ attempts++;
14
+ log.debug(`Checking server availability (attempt ${attempts})`, { url });
15
+ const req = http.get(url, (res) => {
16
+ if (res.statusCode && res.statusCode < 500) {
17
+ timer.end(`✓ Server ready after ${attempts} attempts`);
18
+ resolve();
19
+ }
20
+ else {
21
+ log.debug(`Server returned status ${res.statusCode}, retrying...`);
22
+ retryOrReject();
23
+ }
24
+ });
25
+ req.on('error', (err) => {
26
+ log.debug(`Server check failed: ${err.message}`);
27
+ retryOrReject();
28
+ });
29
+ };
30
+ const retryOrReject = () => {
31
+ const elapsed = Date.now() - startTime;
32
+ if (elapsed < timeout) {
33
+ setTimeout(check, SERVER_CHECK_INTERVAL);
34
+ }
35
+ else {
36
+ timer.end('❌ Timeout');
37
+ reject(new Error(`Server not ready after ${timeout}ms (${attempts} attempts)`));
38
+ }
39
+ };
40
+ check();
41
+ });
42
+ }
43
+ export async function checkOpenCodeInstalled() {
44
+ const timer = log.timer('checkOpenCodeInstalled');
45
+ return new Promise((resolve) => {
46
+ log.debug('Checking if OpenCode is installed...');
47
+ const proc = spawn('opencode', ['--version'], { stdio: 'ignore' });
48
+ proc.on('close', (code) => {
49
+ const installed = code === 0;
50
+ timer.end(installed ? '✓ OpenCode is installed' : '❌ OpenCode not found');
51
+ resolve(installed);
52
+ });
53
+ proc.on('error', (err) => {
54
+ log.debug('Failed to check OpenCode installation', { error: err.message });
55
+ timer.end('❌ Check failed');
56
+ resolve(false);
57
+ });
58
+ });
59
+ }
60
+ export async function isPortAvailable(port, hostname = DEFAULT_HOSTNAME) {
61
+ return new Promise((resolve) => {
62
+ const server = net.createServer();
63
+ server.once('error', (err) => {
64
+ log.debug(`Port ${port} is not available`, { error: err.message });
65
+ resolve(false);
66
+ });
67
+ server.once('listening', () => {
68
+ server.close();
69
+ log.debug(`Port ${port} is available`);
70
+ resolve(true);
71
+ });
72
+ server.listen(port, hostname);
73
+ });
74
+ }
75
+ export async function findAvailablePort(startPort, hostname = DEFAULT_HOSTNAME, maxTries = MAX_PORT_TRIES) {
76
+ const timer = log.timer('findAvailablePort', { startPort, hostname, maxTries });
77
+ log.debug(`Looking for available port starting from ${startPort}`);
78
+ for (let port = startPort; port < startPort + maxTries; port++) {
79
+ if (await isPortAvailable(port, hostname)) {
80
+ timer.end(`✓ Found available port: ${port}`);
81
+ return port;
82
+ }
83
+ log.debug(`Port ${port} is in use, trying next...`);
84
+ }
85
+ timer.end('❌ No available port found');
86
+ throw new Error(`No available port found after ${maxTries} tries starting from ${startPort}`);
87
+ }
88
+ export async function killOrphanOpenCodeProcesses() {
89
+ const timer = log.timer('killOrphanOpenCodeProcesses');
90
+ log.debug('Looking for orphan OpenCode processes (PPID=1)');
91
+ return new Promise((resolve) => {
92
+ if (process.platform === 'win32') {
93
+ killOrphanProcessesOnWindows(resolve, timer);
94
+ }
95
+ else {
96
+ killOrphanProcessesOnUnix(resolve, timer);
97
+ }
98
+ });
99
+ }
100
+ function killOrphanProcessesOnWindows(resolve, timer) {
101
+ log.debug('Using Windows method to find orphan processes');
102
+ const proc = spawn('wmic', [
103
+ 'process',
104
+ 'where',
105
+ 'name="opencode.exe"',
106
+ 'get',
107
+ 'processid,parentprocessid'
108
+ ], { stdio: 'pipe' });
109
+ let output = '';
110
+ proc.stdout?.on('data', (data) => {
111
+ output += data.toString();
112
+ });
113
+ proc.on('close', () => {
114
+ const lines = output.split('\n').filter(line => line.trim());
115
+ const pidsToKill = [];
116
+ lines.forEach(line => {
117
+ const parts = line.trim().split(/\s+/);
118
+ if (parts.length >= 2) {
119
+ const ppid = parts[0];
120
+ const pid = parts[1];
121
+ if (ppid === '1' && pid && !isNaN(Number(pid))) {
122
+ pidsToKill.push(pid);
123
+ }
124
+ }
125
+ });
126
+ if (pidsToKill.length > 0) {
127
+ log.debug(`Found ${pidsToKill.length} orphan processes`, { pids: pidsToKill });
128
+ let killedCount = 0;
129
+ let completedCount = 0;
130
+ pidsToKill.forEach(pid => {
131
+ const killProc = spawn('taskkill', ['/F', '/PID', pid], { stdio: 'ignore' });
132
+ killProc.on('close', (code) => {
133
+ completedCount++;
134
+ if (code === 0) {
135
+ killedCount++;
136
+ log.debug(`Killed orphan process ${pid}`);
137
+ }
138
+ if (completedCount === pidsToKill.length) {
139
+ timer.end(`✓ Killed ${killedCount} orphan processes`);
140
+ resolve(killedCount);
141
+ }
142
+ });
143
+ });
144
+ }
145
+ else {
146
+ log.debug('No orphan processes found');
147
+ timer.end('No orphan processes found');
148
+ resolve(0);
149
+ }
150
+ });
151
+ proc.on('error', (err) => {
152
+ log.debug('Failed to find orphan processes', { error: err.message });
153
+ timer.end('❌ Failed to find orphan processes');
154
+ resolve(0);
155
+ });
156
+ }
157
+ function killOrphanProcessesOnUnix(resolve, timer) {
158
+ log.debug('Using Unix method to find orphan processes');
159
+ const proc = spawn('ps', ['-e', '-o', 'pid,ppid,comm'], { stdio: 'pipe' });
160
+ let output = '';
161
+ proc.stdout?.on('data', (data) => {
162
+ output += data.toString();
163
+ });
164
+ proc.on('close', () => {
165
+ const lines = output.split('\n');
166
+ const pidsToKill = [];
167
+ lines.forEach(line => {
168
+ const trimmed = line.trim();
169
+ if (trimmed.includes('opencode')) {
170
+ const parts = trimmed.split(/\s+/);
171
+ if (parts.length >= 3) {
172
+ const pid = parts[0];
173
+ const ppid = parts[1];
174
+ const comm = parts.slice(2).join(' ');
175
+ if (ppid === '1' && comm.includes('opencode')) {
176
+ pidsToKill.push(pid);
177
+ }
178
+ }
179
+ }
180
+ });
181
+ if (pidsToKill.length > 0) {
182
+ log.debug(`Found ${pidsToKill.length} orphan processes`, { pids: pidsToKill });
183
+ const killProc = spawn('kill', ['-9', ...pidsToKill], { stdio: 'ignore' });
184
+ killProc.on('close', (code) => {
185
+ const killedCount = code === 0 ? pidsToKill.length : 0;
186
+ timer.end(killedCount > 0 ? `✓ Killed ${killedCount} orphan processes` : '❌ Failed to kill processes');
187
+ resolve(killedCount);
188
+ });
189
+ killProc.on('error', () => {
190
+ timer.end('❌ Failed to kill processes');
191
+ resolve(0);
192
+ });
193
+ }
194
+ else {
195
+ log.debug('No orphan processes found');
196
+ timer.end('No orphan processes found');
197
+ resolve(0);
198
+ }
199
+ });
200
+ proc.on('error', (err) => {
201
+ log.debug('Failed to find orphan processes', { error: err.message });
202
+ timer.end('❌ Failed to find orphan processes');
203
+ resolve(0);
204
+ });
205
+ }
206
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/vite/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import http from 'http'\nimport { spawn } from 'child_process'\nimport net from 'net'\nimport {\n DEFAULT_HOSTNAME,\n SERVER_CHECK_INTERVAL,\n MAX_PORT_TRIES,\n} from '../constants.js'\nimport { createLogger, PerformanceTimer } from '../logger.js'\n\nconst log = createLogger('Utils')\n\nexport function waitForServer(url: string, timeout = 10000): Promise<void> {\n const timer = new PerformanceTimer('waitForServer', { url, timeout })\n \n return new Promise((resolve, reject) => {\n const startTime = Date.now()\n let attempts = 0\n\n const check = (): void => {\n attempts++\n log.debug(`Checking server availability (attempt ${attempts})`, { url })\n \n const req = http.get(url, (res) => {\n if (res.statusCode && res.statusCode < 500) {\n timer.end(`✓ Server ready after ${attempts} attempts`)\n resolve()\n } else {\n log.debug(`Server returned status ${res.statusCode}, retrying...`)\n retryOrReject()\n }\n })\n\n req.on('error', (err) => {\n log.debug(`Server check failed: ${err.message}`)\n retryOrReject()\n })\n }\n\n const retryOrReject = (): void => {\n const elapsed = Date.now() - startTime\n if (elapsed < timeout) {\n setTimeout(check, SERVER_CHECK_INTERVAL)\n } else {\n timer.end('❌ Timeout')\n reject(new Error(`Server not ready after ${timeout}ms (${attempts} attempts)`))\n }\n }\n\n check()\n })\n}\n\nexport async function checkOpenCodeInstalled(): Promise<boolean> {\n const timer = log.timer('checkOpenCodeInstalled')\n \n return new Promise((resolve) => {\n log.debug('Checking if OpenCode is installed...')\n \n const proc = spawn('opencode', ['--version'], { stdio: 'ignore' })\n \n proc.on('close', (code) => {\n const installed = code === 0\n timer.end(installed ? '✓ OpenCode is installed' : '❌ OpenCode not found')\n resolve(installed)\n })\n \n proc.on('error', (err) => {\n log.debug('Failed to check OpenCode installation', { error: err.message })\n timer.end('❌ Check failed')\n resolve(false)\n })\n })\n}\n\nexport async function isPortAvailable(port: number, hostname = DEFAULT_HOSTNAME): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer()\n \n server.once('error', (err) => {\n log.debug(`Port ${port} is not available`, { error: (err as Error).message })\n resolve(false)\n })\n \n server.once('listening', () => {\n server.close()\n log.debug(`Port ${port} is available`)\n resolve(true)\n })\n \n server.listen(port, hostname)\n })\n}\n\nexport async function findAvailablePort(\n startPort: number,\n hostname = DEFAULT_HOSTNAME,\n maxTries = MAX_PORT_TRIES\n): Promise<number> {\n const timer = log.timer('findAvailablePort', { startPort, hostname, maxTries })\n \n log.debug(`Looking for available port starting from ${startPort}`)\n \n for (let port = startPort; port < startPort + maxTries; port++) {\n if (await isPortAvailable(port, hostname)) {\n timer.end(`✓ Found available port: ${port}`)\n return port\n }\n log.debug(`Port ${port} is in use, trying next...`)\n }\n \n timer.end('❌ No available port found')\n throw new Error(`No available port found after ${maxTries} tries starting from ${startPort}`)\n}\n\nexport async function killOrphanOpenCodeProcesses(): Promise<number> {\n const timer = log.timer('killOrphanOpenCodeProcesses')\n \n log.debug('Looking for orphan OpenCode processes (PPID=1)')\n \n return new Promise((resolve) => {\n if (process.platform === 'win32') {\n killOrphanProcessesOnWindows(resolve, timer)\n } else {\n killOrphanProcessesOnUnix(resolve, timer)\n }\n })\n}\n\nfunction killOrphanProcessesOnWindows(\n resolve: (value: number) => void,\n timer: PerformanceTimer\n): void {\n log.debug('Using Windows method to find orphan processes')\n \n const proc = spawn('wmic', [\n 'process',\n 'where',\n 'name=\"opencode.exe\"',\n 'get',\n 'processid,parentprocessid'\n ], { stdio: 'pipe' })\n \n let output = ''\n \n proc.stdout?.on('data', (data) => {\n output += data.toString()\n })\n \n proc.on('close', () => {\n const lines = output.split('\\n').filter(line => line.trim())\n const pidsToKill: string[] = []\n \n lines.forEach(line => {\n const parts = line.trim().split(/\\s+/)\n if (parts.length >= 2) {\n const ppid = parts[0]\n const pid = parts[1]\n if (ppid === '1' && pid && !isNaN(Number(pid))) {\n pidsToKill.push(pid)\n }\n }\n })\n \n if (pidsToKill.length > 0) {\n log.debug(`Found ${pidsToKill.length} orphan processes`, { pids: pidsToKill })\n \n let killedCount = 0\n let completedCount = 0\n \n pidsToKill.forEach(pid => {\n const killProc = spawn('taskkill', ['/F', '/PID', pid], { stdio: 'ignore' })\n killProc.on('close', (code) => {\n completedCount++\n if (code === 0) {\n killedCount++\n log.debug(`Killed orphan process ${pid}`)\n }\n \n if (completedCount === pidsToKill.length) {\n timer.end(`✓ Killed ${killedCount} orphan processes`)\n resolve(killedCount)\n }\n })\n })\n } else {\n log.debug('No orphan processes found')\n timer.end('No orphan processes found')\n resolve(0)\n }\n })\n \n proc.on('error', (err) => {\n log.debug('Failed to find orphan processes', { error: err.message })\n timer.end('❌ Failed to find orphan processes')\n resolve(0)\n })\n}\n\nfunction killOrphanProcessesOnUnix(\n resolve: (value: number) => void,\n timer: PerformanceTimer\n): void {\n log.debug('Using Unix method to find orphan processes')\n \n const proc = spawn('ps', ['-e', '-o', 'pid,ppid,comm'], { stdio: 'pipe' })\n let output = ''\n \n proc.stdout?.on('data', (data) => {\n output += data.toString()\n })\n \n proc.on('close', () => {\n const lines = output.split('\\n')\n const pidsToKill: string[] = []\n \n lines.forEach(line => {\n const trimmed = line.trim()\n if (trimmed.includes('opencode')) {\n const parts = trimmed.split(/\\s+/)\n if (parts.length >= 3) {\n const pid = parts[0]\n const ppid = parts[1]\n const comm = parts.slice(2).join(' ')\n \n if (ppid === '1' && comm.includes('opencode')) {\n pidsToKill.push(pid)\n }\n }\n }\n })\n \n if (pidsToKill.length > 0) {\n log.debug(`Found ${pidsToKill.length} orphan processes`, { pids: pidsToKill })\n \n const killProc = spawn('kill', ['-9', ...pidsToKill], { stdio: 'ignore' })\n killProc.on('close', (code) => {\n const killedCount = code === 0 ? pidsToKill.length : 0\n timer.end(killedCount > 0 ? `✓ Killed ${killedCount} orphan processes` : '❌ Failed to kill processes')\n resolve(killedCount)\n })\n \n killProc.on('error', () => {\n timer.end('❌ Failed to kill processes')\n resolve(0)\n })\n } else {\n log.debug('No orphan processes found')\n timer.end('No orphan processes found')\n resolve(0)\n }\n })\n \n proc.on('error', (err) => {\n log.debug('Failed to find orphan processes', { error: err.message })\n timer.end('❌ Failed to find orphan processes')\n resolve(0)\n })\n}\n"]}
package/package.json CHANGED
@@ -1,21 +1,25 @@
1
1
  {
2
2
  "name": "vite-plugin-opencode-assistant",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Embed OpenCode Web UI in your Vite dev server for real-time code modification and preview",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
5
+ "main": "dist/vite/index.js",
6
+ "types": "dist/vite/index.d.ts",
7
7
  "type": "module",
8
+ "workspaces": [
9
+ "example"
10
+ ],
8
11
  "exports": {
9
12
  ".": {
10
- "import": "./dist/index.js",
11
- "types": "./dist/index.d.ts"
13
+ "import": "./dist/vite/index.js",
14
+ "types": "./dist/vite/index.d.ts"
12
15
  }
13
16
  },
14
17
  "files": [
15
18
  "dist"
16
19
  ],
17
20
  "scripts": {
18
- "build": "rm -rf dist && tsc",
21
+ "build": "rm -rf dist && tsc && npm run build:plugins",
22
+ "build:plugins": "vite build --config vite.plugins.config.ts",
19
23
  "dev": "tsc --watch",
20
24
  "test": "vitest",
21
25
  "prepublishOnly": "npm run build"
@@ -33,6 +37,10 @@
33
37
  ],
34
38
  "author": "",
35
39
  "license": "MIT",
40
+ "dependencies": {
41
+ "execa": "^9.6.1",
42
+ "unplugin-vue-inspector": "^2.4.0"
43
+ },
36
44
  "peerDependencies": {
37
45
  "vite": ">=4.0.0"
38
46
  },