@nxuss/lemma 0.9.1 → 0.9.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.
- package/README.md +74 -10
- package/dist/cjs/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/cjs/cli/lemma-proxy.js +52 -1
- package/dist/cjs/cli/lemma-proxy.js.map +1 -1
- package/dist/cjs/mcp/tools.d.ts.map +1 -1
- package/dist/cjs/mcp/tools.js +878 -0
- package/dist/cjs/mcp/tools.js.map +1 -1
- package/dist/cjs/pr-review/PRReviewEngine.d.ts +4 -0
- package/dist/cjs/pr-review/PRReviewEngine.d.ts.map +1 -0
- package/dist/cjs/pr-review/PRReviewEngine.js +203 -0
- package/dist/cjs/pr-review/PRReviewEngine.js.map +1 -0
- package/dist/cjs/pr-review/ReviewStore.d.ts +9 -0
- package/dist/cjs/pr-review/ReviewStore.d.ts.map +1 -0
- package/dist/cjs/pr-review/ReviewStore.js +29 -0
- package/dist/cjs/pr-review/ReviewStore.js.map +1 -0
- package/dist/cjs/pr-review/adapters/AzureDevOpsAdapter.d.ts +18 -0
- package/dist/cjs/pr-review/adapters/AzureDevOpsAdapter.d.ts.map +1 -0
- package/dist/cjs/pr-review/adapters/AzureDevOpsAdapter.js +156 -0
- package/dist/cjs/pr-review/adapters/AzureDevOpsAdapter.js.map +1 -0
- package/dist/cjs/pr-review/adapters/GitHubAdapter.d.ts +18 -0
- package/dist/cjs/pr-review/adapters/GitHubAdapter.d.ts.map +1 -0
- package/dist/cjs/pr-review/adapters/GitHubAdapter.js +106 -0
- package/dist/cjs/pr-review/adapters/GitHubAdapter.js.map +1 -0
- package/dist/cjs/pr-review/adapters/GitLabAdapter.d.ts +19 -0
- package/dist/cjs/pr-review/adapters/GitLabAdapter.d.ts.map +1 -0
- package/dist/cjs/pr-review/adapters/GitLabAdapter.js +137 -0
- package/dist/cjs/pr-review/adapters/GitLabAdapter.js.map +1 -0
- package/dist/cjs/pr-review/adapters/GitPlatformAdapter.d.ts +14 -0
- package/dist/cjs/pr-review/adapters/GitPlatformAdapter.d.ts.map +1 -0
- package/dist/cjs/pr-review/adapters/GitPlatformAdapter.js +3 -0
- package/dist/cjs/pr-review/adapters/GitPlatformAdapter.js.map +1 -0
- package/dist/cjs/pr-review/adapters/index.d.ts +5 -0
- package/dist/cjs/pr-review/adapters/index.d.ts.map +1 -0
- package/dist/cjs/pr-review/adapters/index.js +10 -0
- package/dist/cjs/pr-review/adapters/index.js.map +1 -0
- package/dist/cjs/pr-review/analyzers/QualityGrader.d.ts +7 -0
- package/dist/cjs/pr-review/analyzers/QualityGrader.d.ts.map +1 -0
- package/dist/cjs/pr-review/analyzers/QualityGrader.js +154 -0
- package/dist/cjs/pr-review/analyzers/QualityGrader.js.map +1 -0
- package/dist/cjs/pr-review/analyzers/RegressionDetector.d.ts +7 -0
- package/dist/cjs/pr-review/analyzers/RegressionDetector.d.ts.map +1 -0
- package/dist/cjs/pr-review/analyzers/RegressionDetector.js +151 -0
- package/dist/cjs/pr-review/analyzers/RegressionDetector.js.map +1 -0
- package/dist/cjs/pr-review/analyzers/SecurityScanner.d.ts +7 -0
- package/dist/cjs/pr-review/analyzers/SecurityScanner.d.ts.map +1 -0
- package/dist/cjs/pr-review/analyzers/SecurityScanner.js +110 -0
- package/dist/cjs/pr-review/analyzers/SecurityScanner.js.map +1 -0
- package/dist/cjs/pr-review/analyzers/StaticAnalyzer.d.ts +7 -0
- package/dist/cjs/pr-review/analyzers/StaticAnalyzer.d.ts.map +1 -0
- package/dist/cjs/pr-review/analyzers/StaticAnalyzer.js +237 -0
- package/dist/cjs/pr-review/analyzers/StaticAnalyzer.js.map +1 -0
- package/dist/cjs/pr-review/analyzers/index.d.ts +9 -0
- package/dist/cjs/pr-review/analyzers/index.d.ts.map +1 -0
- package/dist/cjs/pr-review/analyzers/index.js +12 -0
- package/dist/cjs/pr-review/analyzers/index.js.map +1 -0
- package/dist/cjs/pr-review/bridge/BrainBridge.d.ts +23 -0
- package/dist/cjs/pr-review/bridge/BrainBridge.d.ts.map +1 -0
- package/dist/cjs/pr-review/bridge/BrainBridge.js +100 -0
- package/dist/cjs/pr-review/bridge/BrainBridge.js.map +1 -0
- package/dist/cjs/pr-review/bridge/index.d.ts +2 -0
- package/dist/cjs/pr-review/bridge/index.d.ts.map +1 -0
- package/dist/cjs/pr-review/bridge/index.js +6 -0
- package/dist/cjs/pr-review/bridge/index.js.map +1 -0
- package/dist/cjs/pr-review/index.d.ts +5 -0
- package/dist/cjs/pr-review/index.d.ts.map +1 -0
- package/dist/cjs/pr-review/index.js +12 -0
- package/dist/cjs/pr-review/index.js.map +1 -0
- package/dist/cjs/pr-review/reviewRunner.d.ts +25 -0
- package/dist/cjs/pr-review/reviewRunner.d.ts.map +1 -0
- package/dist/cjs/pr-review/reviewRunner.js +97 -0
- package/dist/cjs/pr-review/reviewRunner.js.map +1 -0
- package/dist/cjs/pr-review/types.d.ts +80 -0
- package/dist/cjs/pr-review/types.d.ts.map +1 -0
- package/dist/cjs/pr-review/types.js +3 -0
- package/dist/cjs/pr-review/types.js.map +1 -0
- package/dist/cjs/pr-review/webhook/WebhookServer.d.ts +3 -0
- package/dist/cjs/pr-review/webhook/WebhookServer.d.ts.map +1 -0
- package/dist/cjs/pr-review/webhook/WebhookServer.js +114 -0
- package/dist/cjs/pr-review/webhook/WebhookServer.js.map +1 -0
- package/dist/cjs/pr-review/webhook/index.d.ts +2 -0
- package/dist/cjs/pr-review/webhook/index.d.ts.map +1 -0
- package/dist/cjs/pr-review/webhook/index.js +6 -0
- package/dist/cjs/pr-review/webhook/index.js.map +1 -0
- package/dist/esm/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/esm/cli/lemma-proxy.js +52 -1
- package/dist/esm/cli/lemma-proxy.js.map +1 -1
- package/dist/esm/mcp/tools.d.ts.map +1 -1
- package/dist/esm/mcp/tools.js +878 -0
- package/dist/esm/mcp/tools.js.map +1 -1
- package/dist/esm/pr-review/PRReviewEngine.d.ts +4 -0
- package/dist/esm/pr-review/PRReviewEngine.d.ts.map +1 -0
- package/dist/esm/pr-review/PRReviewEngine.js +199 -0
- package/dist/esm/pr-review/PRReviewEngine.js.map +1 -0
- package/dist/esm/pr-review/ReviewStore.d.ts +9 -0
- package/dist/esm/pr-review/ReviewStore.d.ts.map +1 -0
- package/dist/esm/pr-review/ReviewStore.js +26 -0
- package/dist/esm/pr-review/ReviewStore.js.map +1 -0
- package/dist/esm/pr-review/adapters/AzureDevOpsAdapter.d.ts +18 -0
- package/dist/esm/pr-review/adapters/AzureDevOpsAdapter.d.ts.map +1 -0
- package/dist/esm/pr-review/adapters/AzureDevOpsAdapter.js +149 -0
- package/dist/esm/pr-review/adapters/AzureDevOpsAdapter.js.map +1 -0
- package/dist/esm/pr-review/adapters/GitHubAdapter.d.ts +18 -0
- package/dist/esm/pr-review/adapters/GitHubAdapter.d.ts.map +1 -0
- package/dist/esm/pr-review/adapters/GitHubAdapter.js +99 -0
- package/dist/esm/pr-review/adapters/GitHubAdapter.js.map +1 -0
- package/dist/esm/pr-review/adapters/GitLabAdapter.d.ts +19 -0
- package/dist/esm/pr-review/adapters/GitLabAdapter.d.ts.map +1 -0
- package/dist/esm/pr-review/adapters/GitLabAdapter.js +130 -0
- package/dist/esm/pr-review/adapters/GitLabAdapter.js.map +1 -0
- package/dist/esm/pr-review/adapters/GitPlatformAdapter.d.ts +14 -0
- package/dist/esm/pr-review/adapters/GitPlatformAdapter.d.ts.map +1 -0
- package/dist/esm/pr-review/adapters/GitPlatformAdapter.js +2 -0
- package/dist/esm/pr-review/adapters/GitPlatformAdapter.js.map +1 -0
- package/dist/esm/pr-review/adapters/index.d.ts +5 -0
- package/dist/esm/pr-review/adapters/index.d.ts.map +1 -0
- package/dist/esm/pr-review/adapters/index.js +4 -0
- package/dist/esm/pr-review/adapters/index.js.map +1 -0
- package/dist/esm/pr-review/analyzers/QualityGrader.d.ts +7 -0
- package/dist/esm/pr-review/analyzers/QualityGrader.d.ts.map +1 -0
- package/dist/esm/pr-review/analyzers/QualityGrader.js +151 -0
- package/dist/esm/pr-review/analyzers/QualityGrader.js.map +1 -0
- package/dist/esm/pr-review/analyzers/RegressionDetector.d.ts +7 -0
- package/dist/esm/pr-review/analyzers/RegressionDetector.d.ts.map +1 -0
- package/dist/esm/pr-review/analyzers/RegressionDetector.js +145 -0
- package/dist/esm/pr-review/analyzers/RegressionDetector.js.map +1 -0
- package/dist/esm/pr-review/analyzers/SecurityScanner.d.ts +7 -0
- package/dist/esm/pr-review/analyzers/SecurityScanner.d.ts.map +1 -0
- package/dist/esm/pr-review/analyzers/SecurityScanner.js +107 -0
- package/dist/esm/pr-review/analyzers/SecurityScanner.js.map +1 -0
- package/dist/esm/pr-review/analyzers/StaticAnalyzer.d.ts +7 -0
- package/dist/esm/pr-review/analyzers/StaticAnalyzer.d.ts.map +1 -0
- package/dist/esm/pr-review/analyzers/StaticAnalyzer.js +201 -0
- package/dist/esm/pr-review/analyzers/StaticAnalyzer.js.map +1 -0
- package/dist/esm/pr-review/analyzers/index.d.ts +9 -0
- package/dist/esm/pr-review/analyzers/index.d.ts.map +1 -0
- package/dist/esm/pr-review/analyzers/index.js +5 -0
- package/dist/esm/pr-review/analyzers/index.js.map +1 -0
- package/dist/esm/pr-review/bridge/BrainBridge.d.ts +23 -0
- package/dist/esm/pr-review/bridge/BrainBridge.d.ts.map +1 -0
- package/dist/esm/pr-review/bridge/BrainBridge.js +93 -0
- package/dist/esm/pr-review/bridge/BrainBridge.js.map +1 -0
- package/dist/esm/pr-review/bridge/index.d.ts +2 -0
- package/dist/esm/pr-review/bridge/index.d.ts.map +1 -0
- package/dist/esm/pr-review/bridge/index.js +2 -0
- package/dist/esm/pr-review/bridge/index.js.map +1 -0
- package/dist/esm/pr-review/index.d.ts +5 -0
- package/dist/esm/pr-review/index.d.ts.map +1 -0
- package/dist/esm/pr-review/index.js +3 -0
- package/dist/esm/pr-review/index.js.map +1 -0
- package/dist/esm/pr-review/reviewRunner.d.ts +25 -0
- package/dist/esm/pr-review/reviewRunner.d.ts.map +1 -0
- package/dist/esm/pr-review/reviewRunner.js +92 -0
- package/dist/esm/pr-review/reviewRunner.js.map +1 -0
- package/dist/esm/pr-review/types.d.ts +80 -0
- package/dist/esm/pr-review/types.d.ts.map +1 -0
- package/dist/esm/pr-review/types.js +2 -0
- package/dist/esm/pr-review/types.js.map +1 -0
- package/dist/esm/pr-review/webhook/WebhookServer.d.ts +3 -0
- package/dist/esm/pr-review/webhook/WebhookServer.d.ts.map +1 -0
- package/dist/esm/pr-review/webhook/WebhookServer.js +108 -0
- package/dist/esm/pr-review/webhook/WebhookServer.js.map +1 -0
- package/dist/esm/pr-review/webhook/index.d.ts +2 -0
- package/dist/esm/pr-review/webhook/index.d.ts.map +1 -0
- package/dist/esm/pr-review/webhook/index.js +2 -0
- package/dist/esm/pr-review/webhook/index.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAdapter = getAdapter;
|
|
4
|
+
exports.getTokenForPlatform = getTokenForPlatform;
|
|
5
|
+
exports.runPRReview = runPRReview;
|
|
6
|
+
const PRReviewEngine_1 = require("./PRReviewEngine");
|
|
7
|
+
const ReviewStore_1 = require("./ReviewStore");
|
|
8
|
+
const BrainBridge_1 = require("./bridge/BrainBridge");
|
|
9
|
+
const GitHubAdapter_1 = require("./adapters/GitHubAdapter");
|
|
10
|
+
const AzureDevOpsAdapter_1 = require("./adapters/AzureDevOpsAdapter");
|
|
11
|
+
const GitLabAdapter_1 = require("./adapters/GitLabAdapter");
|
|
12
|
+
const brainBridge = new BrainBridge_1.BrainBridge();
|
|
13
|
+
function getAdapter(platform, token) {
|
|
14
|
+
switch (platform) {
|
|
15
|
+
case "github": return new GitHubAdapter_1.GitHubAdapter(token);
|
|
16
|
+
case "azure": return new AzureDevOpsAdapter_1.AzureDevOpsAdapter(token);
|
|
17
|
+
case "gitlab": return new GitLabAdapter_1.GitLabAdapter(token);
|
|
18
|
+
default: throw new Error(`Unsupported platform: ${platform}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function getTokenForPlatform(platform) {
|
|
22
|
+
const token = process.env[platform === "github" ? "GITHUB_TOKEN"
|
|
23
|
+
: platform === "azure" ? "AZURE_DEVOPS_TOKEN"
|
|
24
|
+
: "GITLAB_TOKEN"] || "";
|
|
25
|
+
if (!token) {
|
|
26
|
+
throw new Error(`No ${platform} token found. Set ${platform === "github" ? "GITHUB_TOKEN"
|
|
27
|
+
: platform === "azure" ? "AZURE_DEVOPS_TOKEN"
|
|
28
|
+
: "GITLAB_TOKEN"} environment variable.`);
|
|
29
|
+
}
|
|
30
|
+
return token;
|
|
31
|
+
}
|
|
32
|
+
async function runPRReview(platform, repo, prNumber, options = {}) {
|
|
33
|
+
const autoApprove = options.autoApprove !== false;
|
|
34
|
+
const threshold = options.threshold || 90;
|
|
35
|
+
const token = getTokenForPlatform(platform);
|
|
36
|
+
const adapter = getAdapter(platform, token);
|
|
37
|
+
const [owner, ...repoParts] = repo.split("/");
|
|
38
|
+
const repoName = repoParts.join("/");
|
|
39
|
+
const [diffFiles, metadata, baseBranch] = await Promise.all([
|
|
40
|
+
adapter.getPRDiff(owner, repoName, prNumber),
|
|
41
|
+
adapter.getPRMetadata(owner, repoName, prNumber),
|
|
42
|
+
adapter.getBaseBranch(owner, repoName, prNumber),
|
|
43
|
+
]);
|
|
44
|
+
const filePaths = diffFiles.map(df => df.path);
|
|
45
|
+
const priorBugs = await brainBridge.findPriorBugs(filePaths);
|
|
46
|
+
let extras = "";
|
|
47
|
+
if (priorBugs.size > 0) {
|
|
48
|
+
extras += `\n\n🧠 **Prior bug context from The Brain:**\n`;
|
|
49
|
+
for (const [file, memories] of priorBugs) {
|
|
50
|
+
extras += `- ${file}: ${memories.length} related memories\n`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const result = (0, PRReviewEngine_1.runAnalysis)(diffFiles, { threshold, autoApprove }, process.cwd(), baseBranch);
|
|
54
|
+
const review = ReviewStore_1.ReviewStore.create({
|
|
55
|
+
score: result.score,
|
|
56
|
+
verdict: result.verdict,
|
|
57
|
+
findings: result.findings,
|
|
58
|
+
summary: result.summary,
|
|
59
|
+
approved: false,
|
|
60
|
+
metadata,
|
|
61
|
+
});
|
|
62
|
+
const commentBody = [
|
|
63
|
+
`# 🔍 Lemma PR Review — #${prNumber} ${metadata.title}`,
|
|
64
|
+
``,
|
|
65
|
+
`**Score:** ${result.score}/100 | **Verdict:** ${result.verdict}`,
|
|
66
|
+
`**Files:** ${diffFiles.length} | **Findings:** ${result.findings.length}`,
|
|
67
|
+
extras,
|
|
68
|
+
``,
|
|
69
|
+
result.summary,
|
|
70
|
+
``,
|
|
71
|
+
`---`,
|
|
72
|
+
`*Review ID: ${review.reviewId}*`,
|
|
73
|
+
].join("\n");
|
|
74
|
+
await adapter.postComment(owner, repoName, prNumber, commentBody);
|
|
75
|
+
let approved = false;
|
|
76
|
+
if (result.verdict === "APPROVED" && autoApprove) {
|
|
77
|
+
await adapter.submitReview(owner, repoName, prNumber, "APPROVE", `✅ Auto-approved by Lemma PR Review (score: ${result.score}/100, threshold: ${threshold})`);
|
|
78
|
+
approved = true;
|
|
79
|
+
}
|
|
80
|
+
else if (result.verdict === "CHANGES_REQUESTED") {
|
|
81
|
+
await adapter.submitReview(owner, repoName, prNumber, "REQUEST_CHANGES", `❌ Changes requested by Lemma PR Review (score: ${result.score}/100, threshold: ${threshold})`);
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
await adapter.setStatus(owner, repoName, metadata.headSha, result.score >= threshold ? "success" : "failure", `Lemma PR Review: ${result.score}/100 — ${result.verdict}`);
|
|
85
|
+
}
|
|
86
|
+
catch { }
|
|
87
|
+
await brainBridge.storeReview(review.reviewId, repo, prNumber, result.score, result.verdict, result.findings, filePaths);
|
|
88
|
+
return {
|
|
89
|
+
reviewId: review.reviewId,
|
|
90
|
+
score: result.score,
|
|
91
|
+
verdict: result.verdict,
|
|
92
|
+
findingsCount: result.findings.length,
|
|
93
|
+
approved,
|
|
94
|
+
summary: result.summary,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=reviewRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewRunner.js","sourceRoot":"","sources":["../../../src/pr-review/reviewRunner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export type Severity = "CRITICAL" | "HIGH" | "MEDIUM" | "LOW";
|
|
2
|
+
export type Verdict = "APPROVED" | "NEUTRAL" | "CHANGES_REQUESTED";
|
|
3
|
+
export type Platform = "github" | "azure" | "gitlab";
|
|
4
|
+
export type ReviewEvent = "APPROVE" | "REQUEST_CHANGES" | "COMMENT";
|
|
5
|
+
export type StatusState = "pending" | "success" | "failure" | "error";
|
|
6
|
+
export interface Finding {
|
|
7
|
+
ruleId: string;
|
|
8
|
+
severity: Severity;
|
|
9
|
+
category: "security" | "regression" | "static" | "quality";
|
|
10
|
+
filePath: string;
|
|
11
|
+
line?: number;
|
|
12
|
+
message: string;
|
|
13
|
+
detail?: string;
|
|
14
|
+
suggestion?: string;
|
|
15
|
+
score: number;
|
|
16
|
+
}
|
|
17
|
+
export interface DiffFile {
|
|
18
|
+
path: string;
|
|
19
|
+
status: "added" | "modified" | "deleted" | "renamed";
|
|
20
|
+
additions: number;
|
|
21
|
+
deletions: number;
|
|
22
|
+
content?: string;
|
|
23
|
+
patch?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface PRMetadata {
|
|
26
|
+
owner: string;
|
|
27
|
+
repo: string;
|
|
28
|
+
prNumber: number;
|
|
29
|
+
title: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
baseBranch: string;
|
|
32
|
+
headBranch: string;
|
|
33
|
+
headSha: string;
|
|
34
|
+
author: string;
|
|
35
|
+
createdAt: string;
|
|
36
|
+
updatedAt: string;
|
|
37
|
+
}
|
|
38
|
+
export interface AnalyzeResult {
|
|
39
|
+
score: number;
|
|
40
|
+
verdict: Verdict;
|
|
41
|
+
findings: Finding[];
|
|
42
|
+
summary: string;
|
|
43
|
+
}
|
|
44
|
+
export interface PRReviewResult {
|
|
45
|
+
reviewId: string;
|
|
46
|
+
score: number;
|
|
47
|
+
verdict: Verdict;
|
|
48
|
+
findings: Finding[];
|
|
49
|
+
summary: string;
|
|
50
|
+
approved: boolean;
|
|
51
|
+
timestamp: string;
|
|
52
|
+
metadata?: PRMetadata;
|
|
53
|
+
}
|
|
54
|
+
export interface AnalyzerConfig {
|
|
55
|
+
threshold: number;
|
|
56
|
+
autoApprove: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface DiffAnalysisRequest {
|
|
59
|
+
diff: string;
|
|
60
|
+
baseBranch?: string;
|
|
61
|
+
workspaceRoot?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface PRReviewRequest {
|
|
64
|
+
platform: Platform;
|
|
65
|
+
repo: string;
|
|
66
|
+
prNumber: number;
|
|
67
|
+
autoApprove?: boolean;
|
|
68
|
+
threshold?: number;
|
|
69
|
+
context?: string;
|
|
70
|
+
}
|
|
71
|
+
export interface WorkflowConfig {
|
|
72
|
+
platform: Platform;
|
|
73
|
+
autoApprove: boolean;
|
|
74
|
+
threshold: number;
|
|
75
|
+
}
|
|
76
|
+
export interface AdapterConfig {
|
|
77
|
+
token?: string;
|
|
78
|
+
baseUrl?: string;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/pr-review/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/pr-review/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebhookServer.d.ts","sourceRoot":"","sources":["../../../../src/pr-review/webhook/WebhookServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAUpD,wBAAgB,mBAAmB,IAAI,MAAM,CA+G5C"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createWebhookRouter = createWebhookRouter;
|
|
7
|
+
const express_1 = require("express");
|
|
8
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
9
|
+
const reviewRunner_1 = require("../reviewRunner");
|
|
10
|
+
function verifyGitHubSignature(payload, signature, secret) {
|
|
11
|
+
const sig = `sha256=${crypto_1.default.createHmac("sha256", secret).update(payload).digest("hex")}`;
|
|
12
|
+
if (signature.length !== sig.length)
|
|
13
|
+
return false;
|
|
14
|
+
return crypto_1.default.timingSafeEqual(Buffer.from(sig), Buffer.from(signature));
|
|
15
|
+
}
|
|
16
|
+
function createWebhookRouter() {
|
|
17
|
+
const router = (0, express_1.Router)();
|
|
18
|
+
router.post("/github", async (req, res) => {
|
|
19
|
+
const signature = req.headers["x-hub-signature-256"];
|
|
20
|
+
const event = req.headers["x-github-event"];
|
|
21
|
+
const webhookSecret = process.env.GITHUB_WEBHOOK_SECRET || "";
|
|
22
|
+
if (webhookSecret && signature) {
|
|
23
|
+
const rawBody = JSON.stringify(req.body);
|
|
24
|
+
if (!verifyGitHubSignature(rawBody, signature, webhookSecret)) {
|
|
25
|
+
res.status(401).json({ error: "Invalid signature" });
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (event !== "pull_request") {
|
|
30
|
+
res.status(200).json({ status: "ignored", event });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const action = req.body.action;
|
|
34
|
+
if (action !== "opened" && action !== "synchronize") {
|
|
35
|
+
res.status(200).json({ status: "ignored", action });
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const pr = req.body.pull_request;
|
|
39
|
+
const repo = req.body.repository;
|
|
40
|
+
const owner = repo.owner.login;
|
|
41
|
+
const repoName = repo.name;
|
|
42
|
+
const prNumber = pr.number;
|
|
43
|
+
const fullRepo = `${owner}/${repoName}`;
|
|
44
|
+
if (!process.env.GITHUB_TOKEN) {
|
|
45
|
+
res.status(500).json({ error: "GITHUB_TOKEN not set" });
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const result = await (0, reviewRunner_1.runPRReview)("github", fullRepo, prNumber, {
|
|
50
|
+
threshold: parseInt(process.env.LEMMA_THRESHOLD || "90", 10),
|
|
51
|
+
autoApprove: process.env.LEMMA_AUTO_APPROVE !== "false",
|
|
52
|
+
});
|
|
53
|
+
res.json({ status: "ok", ...result });
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
console.error("[Webhook] GitHub review failed:", err.message);
|
|
57
|
+
res.status(500).json({ error: err.message });
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
router.post("/azure", async (req, res) => {
|
|
61
|
+
const eventType = req.body.eventType;
|
|
62
|
+
if (eventType !== "git.pullrequest.created" && eventType !== "git.pullrequest.updated") {
|
|
63
|
+
res.status(200).json({ status: "ignored", eventType });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const resource = req.body.resource;
|
|
67
|
+
const prNumber = resource?.pullRequestId;
|
|
68
|
+
const repoName = resource?.repository?.name;
|
|
69
|
+
const projectName = resource?.repository?.project?.name;
|
|
70
|
+
if (!prNumber || !repoName || !projectName || !process.env.AZURE_DEVOPS_TOKEN) {
|
|
71
|
+
res.status(500).json({ error: "Missing required Azure DevOps webhook fields or AZURE_DEVOPS_TOKEN" });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const fullRepo = `${projectName}/${repoName}`;
|
|
75
|
+
try {
|
|
76
|
+
const result = await (0, reviewRunner_1.runPRReview)("azure", fullRepo, prNumber, {
|
|
77
|
+
threshold: parseInt(process.env.LEMMA_THRESHOLD || "90", 10),
|
|
78
|
+
autoApprove: process.env.LEMMA_AUTO_APPROVE !== "false",
|
|
79
|
+
});
|
|
80
|
+
res.json({ status: "ok", ...result });
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
console.error("[Webhook] Azure review failed:", err.message);
|
|
84
|
+
res.status(500).json({ error: err.message });
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
router.post("/gitlab", async (req, res) => {
|
|
88
|
+
const objectKind = req.body.object_kind;
|
|
89
|
+
if (objectKind !== "merge_request") {
|
|
90
|
+
res.status(200).json({ status: "ignored", object_kind: objectKind });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const mr = req.body.object_attributes;
|
|
94
|
+
const prNumber = mr?.iid;
|
|
95
|
+
const projectPath = req.body.project?.path_with_namespace;
|
|
96
|
+
if (!prNumber || !projectPath || !process.env.GITLAB_TOKEN) {
|
|
97
|
+
res.status(500).json({ error: "Missing required GitLab webhook fields or GITLAB_TOKEN" });
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const result = await (0, reviewRunner_1.runPRReview)("gitlab", projectPath, prNumber, {
|
|
102
|
+
threshold: parseInt(process.env.LEMMA_THRESHOLD || "90", 10),
|
|
103
|
+
autoApprove: process.env.LEMMA_AUTO_APPROVE !== "false",
|
|
104
|
+
});
|
|
105
|
+
res.json({ status: "ok", ...result });
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
console.error("[Webhook] GitLab review failed:", err.message);
|
|
109
|
+
res.status(500).json({ error: err.message });
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
return router;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=WebhookServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebhookServer.js","sourceRoot":"","sources":["../../../../src/pr-review/webhook/WebhookServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/pr-review/webhook/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createWebhookRouter = void 0;
|
|
4
|
+
var WebhookServer_1 = require("./WebhookServer");
|
|
5
|
+
Object.defineProperty(exports, "createWebhookRouter", { enumerable: true, get: function () { return WebhookServer_1.createWebhookRouter; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/pr-review/webhook/index.ts"],"names":[],"mappings":";;;AAAA,iDAAsD;AAA7C,oHAAA,mBAAmB,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lemma-proxy.d.ts","sourceRoot":"","sources":["../../../src/cli/lemma-proxy.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"lemma-proxy.d.ts","sourceRoot":"","sources":["../../../src/cli/lemma-proxy.ts"],"names":[],"mappings":";AA2cA,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA4DvF;AAugED,wBAAsB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6KhL"}
|
|
@@ -36,6 +36,7 @@ function ask(query) {
|
|
|
36
36
|
import ComplexityRouter from '../proxy/ComplexityRouter';
|
|
37
37
|
import SemanticScrubber from '../security/SemanticScrubber';
|
|
38
38
|
import CloudSyncClient from '../cloud/CloudSyncClient';
|
|
39
|
+
import { runPRReview } from '../pr-review/reviewRunner';
|
|
39
40
|
import { pruneHistoryMessages, squeezePrompt } from '../utils/ContextSqueezer';
|
|
40
41
|
import { AgentMultiplexer } from '../proxy/AgentMultiplexer';
|
|
41
42
|
import { SseRelay } from '../proxy/SseRelay';
|
|
@@ -366,6 +367,26 @@ enabled = true
|
|
|
366
367
|
}
|
|
367
368
|
}
|
|
368
369
|
catch { }
|
|
370
|
+
// Register lemma MCP server in OpenCode user config (~/.opencode.json)
|
|
371
|
+
const openCodeMcpFile = path.join(os.homedir(), '.opencode.json');
|
|
372
|
+
try {
|
|
373
|
+
let openCodeConfig = {};
|
|
374
|
+
if (fs.existsSync(openCodeMcpFile)) {
|
|
375
|
+
openCodeConfig = JSON.parse(fs.readFileSync(openCodeMcpFile, 'utf8'));
|
|
376
|
+
}
|
|
377
|
+
if (!openCodeConfig.mcp)
|
|
378
|
+
openCodeConfig.mcp = {};
|
|
379
|
+
if (!openCodeConfig.mcp.lemma) {
|
|
380
|
+
openCodeConfig.mcp.lemma = {
|
|
381
|
+
command: "npx",
|
|
382
|
+
args: ["-y", "@nxuss/lemma", "mcp"],
|
|
383
|
+
enabled: true
|
|
384
|
+
};
|
|
385
|
+
fs.writeFileSync(openCodeMcpFile, JSON.stringify(openCodeConfig, null, 2));
|
|
386
|
+
console.log('✅ [OpenCode] Registered lemma MCP server in ~/.opencode.json');
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
catch { }
|
|
369
390
|
console.log(`✅ Auto-configured Lemma for [${project}]`);
|
|
370
391
|
}
|
|
371
392
|
const EVENT_LOG = [];
|
|
@@ -416,6 +437,7 @@ function injectIdeRules(projectName) {
|
|
|
416
437
|
{ name: 'Cursor (v2)', path: path.join(process.cwd(), '.cursor/rules/lemma.mdc') },
|
|
417
438
|
{ name: 'Windsurf', path: path.join(process.cwd(), '.windsurfrules') },
|
|
418
439
|
{ name: 'Cline', path: path.join(process.cwd(), '.clinerules') },
|
|
440
|
+
{ name: 'OpenCode', path: path.join(process.cwd(), '.opencode.md') },
|
|
419
441
|
];
|
|
420
442
|
for (const target of rulesTargets) {
|
|
421
443
|
try {
|
|
@@ -1507,6 +1529,9 @@ class LemmaServer {
|
|
|
1507
1529
|
});
|
|
1508
1530
|
this.app.get('/dashboard/*', (req, res) => res.sendFile(path.join(this.dashboardPath, 'index.html')));
|
|
1509
1531
|
}
|
|
1532
|
+
// Mount PR Review webhook endpoints
|
|
1533
|
+
const { createWebhookRouter } = require('../pr-review/webhook/WebhookServer');
|
|
1534
|
+
this.app.use('/api/webhook', createWebhookRouter());
|
|
1510
1535
|
}
|
|
1511
1536
|
startWorkspaceTimeWatcher() {
|
|
1512
1537
|
const cwd = process.cwd();
|
|
@@ -2331,7 +2356,7 @@ program.command('init')
|
|
|
2331
2356
|
console.log('\n🧠 \x1b[35mAuto-configuring MCP for AI IDEs...\x1b[0m');
|
|
2332
2357
|
}
|
|
2333
2358
|
else {
|
|
2334
|
-
const ans = await ask('\n🧠 Configure MCP servers for your IDEs (Claude, Cursor, Windsurf, VS Code, Kiro, Codex)? (Y/n): ');
|
|
2359
|
+
const ans = await ask('\n🧠 Configure MCP servers for your IDEs (Claude, Cursor, Windsurf, VS Code, OpenCode, Kiro, Codex)? (Y/n): ');
|
|
2335
2360
|
if (ans.toLowerCase() === 'n' || ans.toLowerCase() === 'no') {
|
|
2336
2361
|
opts.configure = false;
|
|
2337
2362
|
console.log('⏭️ Skipping IDE auto-configuration');
|
|
@@ -2607,6 +2632,32 @@ program.command('clipboard')
|
|
|
2607
2632
|
process.exit(1);
|
|
2608
2633
|
}
|
|
2609
2634
|
});
|
|
2635
|
+
program.command('pr-review')
|
|
2636
|
+
.description('Run PR review via CLI (reads env vars for CI/CD: LEMMA_PLATFORM, LEMMA_REPO, LEMMA_PR_NUMBER)')
|
|
2637
|
+
.option('-p, --platform <platform>', 'Git platform (github, azure, gitlab)')
|
|
2638
|
+
.option('-r, --repo <repo>', 'Repository (owner/repo)')
|
|
2639
|
+
.option('-n, --pr-number <number>', 'PR number')
|
|
2640
|
+
.option('-t, --threshold <number>', 'Score threshold for auto-approve', '90')
|
|
2641
|
+
.option('--no-auto-approve', 'Skip auto-approve even if score meets threshold')
|
|
2642
|
+
.action(async (opts) => {
|
|
2643
|
+
const platform = opts.platform || process.env.LEMMA_PLATFORM || '';
|
|
2644
|
+
const repo = opts.repo || process.env.LEMMA_REPO || '';
|
|
2645
|
+
const prNumber = opts.prNumber || process.env.LEMMA_PR_NUMBER || '';
|
|
2646
|
+
const threshold = parseInt(opts.threshold, 10);
|
|
2647
|
+
const autoApprove = opts.autoApprove !== false;
|
|
2648
|
+
if (!platform || !repo || !prNumber) {
|
|
2649
|
+
console.error('Error: platform, repo, and pr-number are required.\nSet via args or LEMMA_PLATFORM, LEMMA_REPO, LEMMA_PR_NUMBER env vars.');
|
|
2650
|
+
process.exit(1);
|
|
2651
|
+
}
|
|
2652
|
+
try {
|
|
2653
|
+
const result = await runPRReview(platform, repo, parseInt(prNumber, 10), { threshold, autoApprove });
|
|
2654
|
+
console.log(JSON.stringify(result, null, 2));
|
|
2655
|
+
}
|
|
2656
|
+
catch (err) {
|
|
2657
|
+
console.error(`PR review failed: ${err.message}`);
|
|
2658
|
+
process.exit(1);
|
|
2659
|
+
}
|
|
2660
|
+
});
|
|
2610
2661
|
if (process.argv[1] && (process.argv[1].includes('lemma') || process.argv[1].endsWith('.cjs') || process.argv[1].endsWith('.js'))) {
|
|
2611
2662
|
// Bare `lemma` with no args → show welcome screen
|
|
2612
2663
|
if (process.argv.length <= 2) {
|