opencode-api-security-testing 4.0.1 → 5.2.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.
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Environment Checker & Auto-Installer
3
+ *
4
+ * Detects missing dependencies and installs them automatically.
5
+ * Supports: Python, pip packages, Playwright, Node.js modules
6
+ */
7
+
8
+ import { execSync } from "child_process";
9
+ import { existsSync } from "fs";
10
+ import { join } from "path";
11
+
12
+ export interface EnvCheckResult {
13
+ python: boolean;
14
+ pythonVersion: string | null;
15
+ pip: boolean;
16
+ playwright: boolean;
17
+ playwrightInstalled: boolean;
18
+ missingPackages: string[];
19
+ autoInstalled: string[];
20
+ errors: string[];
21
+ }
22
+
23
+ /**
24
+ * Run shell command safely
25
+ */
26
+ function runCommand(cmd: string, timeout = 30000): { success: boolean; output: string; error: string } {
27
+ try {
28
+ const output = execSync(cmd, {
29
+ encoding: "utf-8",
30
+ timeout,
31
+ stdio: ["pipe", "pipe", "pipe"]
32
+ });
33
+ return { success: true, output: output.trim(), error: "" };
34
+ } catch (error) {
35
+ const err = error as { stdout?: string; stderr?: string; message?: string };
36
+ return {
37
+ success: false,
38
+ output: err.stdout || "",
39
+ error: err.stderr || err.message || "Unknown error"
40
+ };
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Check if Python is available
46
+ */
47
+ function checkPython(): { available: boolean; version: string | null } {
48
+ // Try python3 first, then python
49
+ for (const cmd of ["python3 --version", "python --version"]) {
50
+ const result = runCommand(cmd, 5000);
51
+ if (result.success) {
52
+ const versionMatch = result.output.match(/Python\s+(\d+\.\d+\.\d+)/i) ||
53
+ result.error.match(/Python\s+(\d+\.\d+\.\d+)/i);
54
+ return {
55
+ available: true,
56
+ version: versionMatch ? versionMatch[1] : "unknown"
57
+ };
58
+ }
59
+ }
60
+ return { available: false, version: null };
61
+ }
62
+
63
+ /**
64
+ * Check if pip is available
65
+ */
66
+ function checkPip(): boolean {
67
+ for (const cmd of ["pip3 --version", "pip --version", "python3 -m pip --version", "python -m pip --version"]) {
68
+ const result = runCommand(cmd, 5000);
69
+ if (result.success) return true;
70
+ }
71
+ return false;
72
+ }
73
+
74
+ /**
75
+ * Check if a Python package is installed
76
+ */
77
+ function checkPythonPackage(packageName: string): boolean {
78
+ const result = runCommand(`python3 -c "import ${packageName}" 2>/dev/null || python -c "import ${packageName}" 2>/dev/null`, 5000);
79
+ return result.success;
80
+ }
81
+
82
+ /**
83
+ * Install a Python package
84
+ */
85
+ function installPythonPackage(packageName: string): { success: boolean; error: string } {
86
+ for (const cmd of [
87
+ `pip3 install -q ${packageName}`,
88
+ `pip install -q ${packageName}`,
89
+ `python3 -m pip install -q ${packageName}`,
90
+ `python -m pip install -q ${packageName}`
91
+ ]) {
92
+ const result = runCommand(cmd, 60000);
93
+ if (result.success) return { success: true, error: "" };
94
+ }
95
+ return { success: false, error: `Failed to install ${packageName}` };
96
+ }
97
+
98
+ /**
99
+ * Check if Playwright browsers are installed
100
+ */
101
+ function checkPlaywright(): { installed: boolean; browsersInstalled: boolean } {
102
+ // Check if playwright Python package is installed
103
+ const hasPackage = checkPythonPackage("playwright");
104
+
105
+ // Check if browsers are installed
106
+ const homeDir = process.env.HOME || process.env.USERPROFILE || "/root";
107
+ const pwCachePath = join(homeDir, ".cache", "ms-playwright");
108
+ const browsersInstalled = existsSync(pwCachePath);
109
+
110
+ return { installed: hasPackage, browsersInstalled };
111
+ }
112
+
113
+ /**
114
+ * Install Playwright
115
+ */
116
+ function installPlaywright(): { success: boolean; error: string } {
117
+ console.log("[env-checker] Installing Playwright Python package...");
118
+ const pkgResult = installPythonPackage("playwright");
119
+ if (!pkgResult.success) return pkgResult;
120
+
121
+ console.log("[env-checker] Installing Playwright browsers (chromium)...");
122
+ const browserResult = runCommand("python3 -m playwright install chromium", 300000);
123
+ if (browserResult.success) {
124
+ return { success: true, error: "" };
125
+ }
126
+
127
+ // Try with python fallback
128
+ const browserResult2 = runCommand("python -m playwright install chromium", 300000);
129
+ if (browserResult2.success) {
130
+ return { success: true, error: "" };
131
+ }
132
+
133
+ return { success: false, error: `Failed to install Playwright browsers: ${browserResult.error}` };
134
+ }
135
+
136
+ /**
137
+ * Check if Node.js is available
138
+ */
139
+ function checkNode(): { available: boolean; version: string | null } {
140
+ const result = runCommand("node --version", 5000);
141
+ if (result.success) {
142
+ return { available: true, version: result.output };
143
+ }
144
+ return { available: false, version: null };
145
+ }
146
+
147
+ /**
148
+ * Run full environment check and auto-install missing dependencies
149
+ */
150
+ export function checkAndFixEnvironment(): EnvCheckResult {
151
+ const result: EnvCheckResult = {
152
+ python: false,
153
+ pythonVersion: null,
154
+ pip: false,
155
+ playwright: false,
156
+ playwrightInstalled: false,
157
+ missingPackages: [],
158
+ autoInstalled: [],
159
+ errors: []
160
+ };
161
+
162
+ console.log("[env-checker] Starting environment check...");
163
+
164
+ // Check Python
165
+ const pythonCheck = checkPython();
166
+ result.python = pythonCheck.available;
167
+ result.pythonVersion = pythonCheck.version;
168
+
169
+ if (!result.python) {
170
+ result.errors.push("Python 3 is not installed. Please install Python 3.8+ from https://python.org");
171
+ return result;
172
+ }
173
+
174
+ console.log(`[env-checker] Python ${result.pythonVersion} detected`);
175
+
176
+ // Check pip
177
+ result.pip = checkPip();
178
+ if (!result.pip) {
179
+ result.errors.push("pip is not available. Please install pip.");
180
+ return result;
181
+ }
182
+
183
+ // Check required Python packages
184
+ const requiredPackages = ["requests", "beautifulsoup4"];
185
+ const optionalPackages = ["playwright", "websocket-client", "urllib3"];
186
+
187
+ for (const pkg of requiredPackages) {
188
+ if (!checkPythonPackage(pkg)) {
189
+ console.log(`[env-checker] Installing missing package: ${pkg}`);
190
+ const installResult = installPythonPackage(pkg);
191
+ if (installResult.success) {
192
+ result.autoInstalled.push(pkg);
193
+ console.log(`[env-checker] ✓ ${pkg} installed`);
194
+ } else {
195
+ result.missingPackages.push(pkg);
196
+ result.errors.push(`Failed to install ${pkg}: ${installResult.error}`);
197
+ }
198
+ }
199
+ }
200
+
201
+ // Check optional packages
202
+ for (const pkg of optionalPackages) {
203
+ if (!checkPythonPackage(pkg)) {
204
+ console.log(`[env-checker] Installing optional package: ${pkg}`);
205
+ const installResult = installPythonPackage(pkg);
206
+ if (installResult.success) {
207
+ result.autoInstalled.push(pkg);
208
+ console.log(`[env-checker] ✓ ${pkg} installed`);
209
+ } else {
210
+ result.missingPackages.push(pkg);
211
+ }
212
+ }
213
+ }
214
+
215
+ // Check Playwright
216
+ const pwCheck = checkPlaywright();
217
+ result.playwright = pwCheck.installed;
218
+ result.playwrightInstalled = pwCheck.browsersInstalled;
219
+
220
+ if (!pwCheck.installed || !pwCheck.browsersInstalled) {
221
+ console.log("[env-checker] Playwright not fully installed, installing...");
222
+ const pwInstallResult = installPlaywright();
223
+ if (pwInstallResult.success) {
224
+ result.playwright = true;
225
+ result.playwrightInstalled = true;
226
+ result.autoInstalled.push("playwright+browsers");
227
+ console.log("[env-checker] ✓ Playwright installed");
228
+ } else {
229
+ result.errors.push(`Playwright installation failed: ${pwInstallResult.error}`);
230
+ console.log(`[env-checker] ⚠ Playwright installation failed: ${pwInstallResult.error}`);
231
+ console.log("[env-checker] browser_collect tool will not work until Playwright is installed");
232
+ }
233
+ }
234
+
235
+ // Summary
236
+ console.log("\n[env-checker] Environment check complete:");
237
+ console.log(` Python: ${result.python ? "✓ " + result.pythonVersion : "✗"}`);
238
+ console.log(` pip: ${result.pip ? "✓" : "✗"}`);
239
+ console.log(` Playwright: ${result.playwrightInstalled ? "✓" : "✗"}`);
240
+ if (result.autoInstalled.length > 0) {
241
+ console.log(` Auto-installed: ${result.autoInstalled.join(", ")}`);
242
+ }
243
+ if (result.errors.length > 0) {
244
+ console.log(` Errors: ${result.errors.join("; ")}`);
245
+ }
246
+
247
+ return result;
248
+ }
249
+
250
+ /**
251
+ * Generate a shell command prefix that ensures dependencies are installed
252
+ */
253
+ export function getDepCheckCommand(ctx: { directory: string }): string {
254
+ const { existsSync } = require("fs");
255
+ const { join } = require("path");
256
+
257
+ const skillPath = join(ctx.directory, "skills/api-security-testing");
258
+ const reqFile = join(skillPath, "requirements.txt");
259
+
260
+ if (existsSync(reqFile)) {
261
+ return `pip install -q -r "${reqFile}" 2>/dev/null; `;
262
+ }
263
+ return "";
264
+ }