@oculum/cli 1.0.5 → 1.0.7
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 +4 -103
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -43131,103 +43131,6 @@ async function callBackendAPI(files, depth, apiKey, repoInfo) {
|
|
|
43131
43131
|
}
|
|
43132
43132
|
return data.result;
|
|
43133
43133
|
}
|
|
43134
|
-
async function callBackendAPIStream(files, depth, apiKey, repoInfo, onProgress) {
|
|
43135
|
-
const baseUrl = getApiBaseUrl();
|
|
43136
|
-
const streamUrl = `${baseUrl}/v1/scan/stream`;
|
|
43137
|
-
try {
|
|
43138
|
-
const response = await fetch(streamUrl, {
|
|
43139
|
-
method: "POST",
|
|
43140
|
-
headers: {
|
|
43141
|
-
"Content-Type": "application/json",
|
|
43142
|
-
"Authorization": `Bearer ${apiKey}`,
|
|
43143
|
-
"X-Oculum-Client": "cli",
|
|
43144
|
-
"X-Oculum-Version": "1.0.0"
|
|
43145
|
-
},
|
|
43146
|
-
body: JSON.stringify({
|
|
43147
|
-
files,
|
|
43148
|
-
depth,
|
|
43149
|
-
repoName: repoInfo.name,
|
|
43150
|
-
repoUrl: repoInfo.url,
|
|
43151
|
-
branch: repoInfo.branch
|
|
43152
|
-
})
|
|
43153
|
-
});
|
|
43154
|
-
if (!response.ok) {
|
|
43155
|
-
console.warn(`[API] SSE endpoint failed with ${response.status}, falling back to regular POST`);
|
|
43156
|
-
return await callBackendAPI(files, depth, apiKey, repoInfo);
|
|
43157
|
-
}
|
|
43158
|
-
if (!response.body) {
|
|
43159
|
-
throw new APIError("Response body is empty", 500);
|
|
43160
|
-
}
|
|
43161
|
-
const reader = response.body.getReader();
|
|
43162
|
-
const decoder = new TextDecoder();
|
|
43163
|
-
let buffer = "";
|
|
43164
|
-
let result = null;
|
|
43165
|
-
while (true) {
|
|
43166
|
-
const { done, value } = await reader.read();
|
|
43167
|
-
if (done) break;
|
|
43168
|
-
buffer += decoder.decode(value, { stream: true });
|
|
43169
|
-
const lines = buffer.split("\n");
|
|
43170
|
-
buffer = lines.pop() || "";
|
|
43171
|
-
let currentEvent = null;
|
|
43172
|
-
let currentData = null;
|
|
43173
|
-
for (const line of lines) {
|
|
43174
|
-
if (line.startsWith("event: ")) {
|
|
43175
|
-
currentEvent = line.slice(7).trim();
|
|
43176
|
-
} else if (line.startsWith("data: ")) {
|
|
43177
|
-
currentData = line.slice(6).trim();
|
|
43178
|
-
} else if (line === "" && currentEvent && currentData) {
|
|
43179
|
-
try {
|
|
43180
|
-
const data = JSON.parse(currentData);
|
|
43181
|
-
switch (currentEvent) {
|
|
43182
|
-
case "progress":
|
|
43183
|
-
if (onProgress) {
|
|
43184
|
-
onProgress({
|
|
43185
|
-
status: data.status,
|
|
43186
|
-
message: data.message || "",
|
|
43187
|
-
filesProcessed: data.filesProcessed || 0,
|
|
43188
|
-
totalFiles: data.totalFiles || 0,
|
|
43189
|
-
vulnerabilitiesFound: data.vulnerabilitiesFound || 0
|
|
43190
|
-
});
|
|
43191
|
-
}
|
|
43192
|
-
break;
|
|
43193
|
-
case "complete":
|
|
43194
|
-
if (!data.result) {
|
|
43195
|
-
console.error("[API] Complete event received but no result in data:", data);
|
|
43196
|
-
throw new APIError("Backend scan completed but returned no result data", 500);
|
|
43197
|
-
}
|
|
43198
|
-
result = data.result;
|
|
43199
|
-
break;
|
|
43200
|
-
case "error":
|
|
43201
|
-
console.error("[API] Backend sent error event:", data);
|
|
43202
|
-
throw new APIError(
|
|
43203
|
-
data.message || data.error || "Scan failed",
|
|
43204
|
-
data.status || 500,
|
|
43205
|
-
data.error
|
|
43206
|
-
);
|
|
43207
|
-
}
|
|
43208
|
-
} catch (parseError) {
|
|
43209
|
-
if (parseError instanceof APIError) throw parseError;
|
|
43210
|
-
console.error("[API] Failed to parse SSE event:", parseError);
|
|
43211
|
-
}
|
|
43212
|
-
currentEvent = null;
|
|
43213
|
-
currentData = null;
|
|
43214
|
-
}
|
|
43215
|
-
}
|
|
43216
|
-
}
|
|
43217
|
-
if (!result) {
|
|
43218
|
-
console.error("[API] Stream ended without receiving complete event");
|
|
43219
|
-
throw new APIError("No result received from stream", 500);
|
|
43220
|
-
}
|
|
43221
|
-
console.log("[API] SSE stream completed successfully");
|
|
43222
|
-
return result;
|
|
43223
|
-
} catch (error) {
|
|
43224
|
-
if (error instanceof APIError) {
|
|
43225
|
-
throw error;
|
|
43226
|
-
}
|
|
43227
|
-
console.warn("[API] SSE streaming failed, falling back to regular POST:", error);
|
|
43228
|
-
return await callBackendAPI(files, depth, apiKey, repoInfo);
|
|
43229
|
-
}
|
|
43230
|
-
}
|
|
43231
43134
|
async function verifyApiKey(apiKey) {
|
|
43232
43135
|
const baseUrl = getApiBaseUrl();
|
|
43233
43136
|
const url = `${baseUrl}/v1/verify-key`;
|
|
@@ -44045,8 +43948,8 @@ async function runScanOnce(targetPath, options) {
|
|
|
44045
43948
|
spinner.start("Starting scan...");
|
|
44046
43949
|
const hasLocalAI = !!process.env.ANTHROPIC_API_KEY;
|
|
44047
43950
|
if (options.depth !== "cheap" && isAuthenticated() && !hasLocalAI) {
|
|
44048
|
-
spinner.text = `Backend ${options.depth} scan
|
|
44049
|
-
result = await
|
|
43951
|
+
spinner.text = `Backend ${options.depth} scan analyzing ${files.length} files...`;
|
|
43952
|
+
result = await callBackendAPI(
|
|
44050
43953
|
files,
|
|
44051
43954
|
options.depth,
|
|
44052
43955
|
config.apiKey,
|
|
@@ -44054,9 +43957,7 @@ async function runScanOnce(targetPath, options) {
|
|
|
44054
43957
|
name: (0, import_path3.basename)((0, import_path3.resolve)(targetPath)),
|
|
44055
43958
|
url: "",
|
|
44056
43959
|
branch: "local"
|
|
44057
|
-
}
|
|
44058
|
-
onProgress
|
|
44059
|
-
// Stream real-time progress from backend
|
|
43960
|
+
}
|
|
44060
43961
|
);
|
|
44061
43962
|
spinner.succeed(`Backend ${options.depth} scan complete`);
|
|
44062
43963
|
} else {
|
|
@@ -48367,7 +48268,7 @@ var usageCommand = new Command("usage").description("Show current usage and quot
|
|
|
48367
48268
|
|
|
48368
48269
|
// src/index.ts
|
|
48369
48270
|
var program2 = new Command();
|
|
48370
|
-
program2.name("oculum").description("AI-native security scanner for detecting vulnerabilities in LLM-generated code").version("1.0.
|
|
48271
|
+
program2.name("oculum").description("AI-native security scanner for detecting vulnerabilities in LLM-generated code").version("1.0.7").addHelpText("after", `
|
|
48371
48272
|
Quick Start:
|
|
48372
48273
|
$ oculum scan . Scan current directory (free)
|
|
48373
48274
|
$ oculum ui Interactive mode with guided setup
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oculum/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "AI-native security scanner CLI for detecting vulnerabilities in AI-generated code, BYOK patterns, and modern web applications",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"url": "https://github.com/flexipie/oculum/issues"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "esbuild src/index.ts --bundle --platform=node --target=node18 --outfile=dist/index.js --banner:js=\"#!/usr/bin/env node\" --define:process.env.OCULUM_API_URL='undefined' --define:VERSION='\"1.0.
|
|
21
|
+
"build": "esbuild src/index.ts --bundle --platform=node --target=node18 --outfile=dist/index.js --banner:js=\"#!/usr/bin/env node\" --define:process.env.OCULUM_API_URL='undefined' --define:VERSION='\"1.0.7\"'",
|
|
22
22
|
"dev": "npm run build -- --watch",
|
|
23
23
|
"test": "echo \"No tests configured yet\"",
|
|
24
24
|
"lint": "eslint src/"
|