@diff-review-system/drs 1.1.2 → 2.1.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/.opencode/agent/describe/pr-describer.md +221 -0
- package/.opencode/agent/review/documentation.md +56 -0
- package/.opencode/agent/review/performance.md +32 -139
- package/.opencode/agent/review/quality.md +36 -113
- package/.opencode/agent/review/security.md +32 -97
- package/.opencode/agent/review/style.md +4 -0
- package/.opencode/agent/review/unified-reviewer.md +74 -0
- package/.opencode/opencode.jsonc +4 -29
- package/.opencode/tool/write_json_output.ts +24 -0
- package/README.md +48 -21
- package/dist/ci/runner.d.ts.map +1 -1
- package/dist/ci/runner.js +2 -0
- package/dist/ci/runner.js.map +1 -1
- package/dist/cli/describe-mr.d.ts +11 -0
- package/dist/cli/describe-mr.d.ts.map +1 -0
- package/dist/cli/describe-mr.js +104 -0
- package/dist/cli/describe-mr.js.map +1 -0
- package/dist/cli/describe-pr.d.ts +12 -0
- package/dist/cli/describe-pr.d.ts.map +1 -0
- package/dist/cli/describe-pr.js +105 -0
- package/dist/cli/describe-pr.js.map +1 -0
- package/dist/cli/index.js +222 -16
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +273 -145
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/post-comments.d.ts +16 -0
- package/dist/cli/post-comments.d.ts.map +1 -0
- package/dist/cli/post-comments.js +222 -0
- package/dist/cli/post-comments.js.map +1 -0
- package/dist/cli/review-local.d.ts +3 -0
- package/dist/cli/review-local.d.ts.map +1 -1
- package/dist/cli/review-local.js +44 -18
- package/dist/cli/review-local.js.map +1 -1
- package/dist/cli/review-mr.d.ts +6 -0
- package/dist/cli/review-mr.d.ts.map +1 -1
- package/dist/cli/review-mr.js +63 -7
- package/dist/cli/review-mr.js.map +1 -1
- package/dist/cli/review-pr.d.ts +6 -0
- package/dist/cli/review-pr.d.ts.map +1 -1
- package/dist/cli/review-pr.js +8 -1
- package/dist/cli/review-pr.js.map +1 -1
- package/dist/cli/show-changes.d.ts +15 -0
- package/dist/cli/show-changes.d.ts.map +1 -0
- package/dist/cli/show-changes.js +184 -0
- package/dist/cli/show-changes.js.map +1 -0
- package/dist/github/platform-adapter.d.ts.map +1 -1
- package/dist/github/platform-adapter.js +4 -2
- package/dist/github/platform-adapter.js.map +1 -1
- package/dist/gitlab/client.d.ts.map +1 -1
- package/dist/gitlab/client.js +1 -1
- package/dist/gitlab/client.js.map +1 -1
- package/dist/gitlab/platform-adapter.d.ts.map +1 -1
- package/dist/gitlab/platform-adapter.js +6 -5
- package/dist/gitlab/platform-adapter.js.map +1 -1
- package/dist/lib/change-summary.d.ts +8 -0
- package/dist/lib/change-summary.d.ts.map +1 -0
- package/dist/lib/change-summary.js +2 -0
- package/dist/lib/change-summary.js.map +1 -0
- package/dist/lib/comment-formatter.d.ts +3 -2
- package/dist/lib/comment-formatter.d.ts.map +1 -1
- package/dist/lib/comment-formatter.js +16 -2
- package/dist/lib/comment-formatter.js.map +1 -1
- package/dist/lib/comment-formatter.test.d.ts +2 -0
- package/dist/lib/comment-formatter.test.d.ts.map +1 -0
- package/dist/lib/comment-formatter.test.js +607 -0
- package/dist/lib/comment-formatter.test.js.map +1 -0
- package/dist/lib/comment-manager.test.d.ts +2 -0
- package/dist/lib/comment-manager.test.d.ts.map +1 -0
- package/dist/lib/comment-manager.test.js +618 -0
- package/dist/lib/comment-manager.test.js.map +1 -0
- package/dist/lib/comment-poster.d.ts +21 -0
- package/dist/lib/comment-poster.d.ts.map +1 -0
- package/dist/lib/comment-poster.js +96 -0
- package/dist/lib/comment-poster.js.map +1 -0
- package/dist/lib/comment-poster.test.d.ts +5 -0
- package/dist/lib/comment-poster.test.d.ts.map +1 -0
- package/dist/lib/comment-poster.test.js +215 -0
- package/dist/lib/comment-poster.test.js.map +1 -0
- package/dist/lib/config-model-overrides.test.js +71 -41
- package/dist/lib/config-model-overrides.test.js.map +1 -1
- package/dist/lib/config.d.ts +65 -7
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +122 -22
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/config.test.js +31 -2
- package/dist/lib/config.test.js.map +1 -1
- package/dist/lib/context-compression.d.ts +19 -0
- package/dist/lib/context-compression.d.ts.map +1 -0
- package/dist/lib/context-compression.js +170 -0
- package/dist/lib/context-compression.js.map +1 -0
- package/dist/lib/context-compression.test.d.ts +2 -0
- package/dist/lib/context-compression.test.d.ts.map +1 -0
- package/dist/lib/context-compression.test.js +33 -0
- package/dist/lib/context-compression.test.js.map +1 -0
- package/dist/lib/context-loader.d.ts.map +1 -1
- package/dist/lib/context-loader.js +8 -1
- package/dist/lib/context-loader.js.map +1 -1
- package/dist/lib/context-loader.test.d.ts +2 -0
- package/dist/lib/context-loader.test.d.ts.map +1 -0
- package/dist/lib/context-loader.test.js +207 -0
- package/dist/lib/context-loader.test.js.map +1 -0
- package/dist/lib/describe-core.d.ts +9 -0
- package/dist/lib/describe-core.d.ts.map +1 -0
- package/dist/lib/describe-core.js +71 -0
- package/dist/lib/describe-core.js.map +1 -0
- package/dist/lib/describe-core.test.d.ts +2 -0
- package/dist/lib/describe-core.test.d.ts.map +1 -0
- package/dist/lib/describe-core.test.js +208 -0
- package/dist/lib/describe-core.test.js.map +1 -0
- package/dist/lib/describe-output-path.test.d.ts +2 -0
- package/dist/lib/describe-output-path.test.d.ts.map +1 -0
- package/dist/lib/describe-output-path.test.js +51 -0
- package/dist/lib/describe-output-path.test.js.map +1 -0
- package/dist/lib/describe-parser.d.ts +3 -0
- package/dist/lib/describe-parser.d.ts.map +1 -0
- package/dist/lib/describe-parser.js +163 -0
- package/dist/lib/describe-parser.js.map +1 -0
- package/dist/lib/describe-parser.test.d.ts +2 -0
- package/dist/lib/describe-parser.test.d.ts.map +1 -0
- package/dist/lib/describe-parser.test.js +282 -0
- package/dist/lib/describe-parser.test.js.map +1 -0
- package/dist/lib/description-executor.d.ts +22 -0
- package/dist/lib/description-executor.d.ts.map +1 -0
- package/dist/lib/description-executor.js +72 -0
- package/dist/lib/description-executor.js.map +1 -0
- package/dist/lib/description-formatter.d.ts +37 -0
- package/dist/lib/description-formatter.d.ts.map +1 -0
- package/dist/lib/description-formatter.js +219 -0
- package/dist/lib/description-formatter.js.map +1 -0
- package/dist/lib/diff-parser.d.ts +11 -0
- package/dist/lib/diff-parser.d.ts.map +1 -1
- package/dist/lib/diff-parser.js +37 -0
- package/dist/lib/diff-parser.js.map +1 -1
- package/dist/lib/issue-parser.d.ts +1 -1
- package/dist/lib/issue-parser.d.ts.map +1 -1
- package/dist/lib/issue-parser.js +16 -14
- package/dist/lib/issue-parser.js.map +1 -1
- package/dist/lib/json-output-schema.d.ts +207 -0
- package/dist/lib/json-output-schema.d.ts.map +1 -0
- package/dist/lib/json-output-schema.js +124 -0
- package/dist/lib/json-output-schema.js.map +1 -0
- package/dist/lib/json-output-schema.test.d.ts +2 -0
- package/dist/lib/json-output-schema.test.d.ts.map +1 -0
- package/dist/lib/json-output-schema.test.js +92 -0
- package/dist/lib/json-output-schema.test.js.map +1 -0
- package/dist/lib/json-output.d.ts +43 -0
- package/dist/lib/json-output.d.ts.map +1 -0
- package/dist/lib/json-output.js +34 -0
- package/dist/lib/json-output.js.map +1 -0
- package/dist/lib/output-paths.d.ts +6 -0
- package/dist/lib/output-paths.d.ts.map +1 -0
- package/dist/lib/output-paths.js +5 -0
- package/dist/lib/output-paths.js.map +1 -0
- package/dist/lib/platform-client.d.ts +1 -1
- package/dist/lib/platform-client.d.ts.map +1 -1
- package/dist/lib/repository-validator.d.ts +57 -0
- package/dist/lib/repository-validator.d.ts.map +1 -0
- package/dist/lib/repository-validator.js +225 -0
- package/dist/lib/repository-validator.js.map +1 -0
- package/dist/lib/repository-validator.test.d.ts +5 -0
- package/dist/lib/repository-validator.test.d.ts.map +1 -0
- package/dist/lib/repository-validator.test.js +341 -0
- package/dist/lib/repository-validator.test.js.map +1 -0
- package/dist/lib/review-core.d.ts +66 -0
- package/dist/lib/review-core.d.ts.map +1 -0
- package/dist/lib/review-core.js +449 -0
- package/dist/lib/review-core.js.map +1 -0
- package/dist/lib/review-core.test.d.ts +2 -0
- package/dist/lib/review-core.test.d.ts.map +1 -0
- package/dist/lib/review-core.test.js +552 -0
- package/dist/lib/review-core.test.js.map +1 -0
- package/dist/lib/review-orchestrator.d.ts +27 -10
- package/dist/lib/review-orchestrator.d.ts.map +1 -1
- package/dist/lib/review-orchestrator.js +51 -110
- package/dist/lib/review-orchestrator.js.map +1 -1
- package/dist/lib/review-orchestrator.test.d.ts +2 -0
- package/dist/lib/review-orchestrator.test.d.ts.map +1 -0
- package/dist/lib/review-orchestrator.test.js +413 -0
- package/dist/lib/review-orchestrator.test.js.map +1 -0
- package/dist/lib/review-output-path.test.d.ts +2 -0
- package/dist/lib/review-output-path.test.d.ts.map +1 -0
- package/dist/lib/review-output-path.test.js +83 -0
- package/dist/lib/review-output-path.test.js.map +1 -0
- package/dist/lib/review-parser.d.ts +2 -0
- package/dist/lib/review-parser.d.ts.map +1 -0
- package/dist/lib/review-parser.js +100 -0
- package/dist/lib/review-parser.js.map +1 -0
- package/dist/lib/unified-review-executor.d.ts +21 -4
- package/dist/lib/unified-review-executor.d.ts.map +1 -1
- package/dist/lib/unified-review-executor.js +84 -151
- package/dist/lib/unified-review-executor.js.map +1 -1
- package/dist/lib/unified-review-executor.test.d.ts +5 -0
- package/dist/lib/unified-review-executor.test.d.ts.map +1 -0
- package/dist/lib/unified-review-executor.test.js +350 -0
- package/dist/lib/unified-review-executor.test.js.map +1 -0
- package/dist/lib/write-json-output.d.ts +13 -0
- package/dist/lib/write-json-output.d.ts.map +1 -0
- package/dist/lib/write-json-output.js +37 -0
- package/dist/lib/write-json-output.js.map +1 -0
- package/dist/opencode/agent-loader.d.ts +3 -4
- package/dist/opencode/agent-loader.d.ts.map +1 -1
- package/dist/opencode/agent-loader.js +48 -34
- package/dist/opencode/agent-loader.js.map +1 -1
- package/dist/opencode/agent-skill-overlay.d.ts +11 -0
- package/dist/opencode/agent-skill-overlay.d.ts.map +1 -0
- package/dist/opencode/agent-skill-overlay.js +164 -0
- package/dist/opencode/agent-skill-overlay.js.map +1 -0
- package/dist/opencode/client.d.ts +11 -3
- package/dist/opencode/client.d.ts.map +1 -1
- package/dist/opencode/client.js +237 -71
- package/dist/opencode/client.js.map +1 -1
- package/dist/opencode/client.test.d.ts +2 -0
- package/dist/opencode/client.test.d.ts.map +1 -0
- package/dist/opencode/client.test.js +317 -0
- package/dist/opencode/client.test.js.map +1 -0
- package/dist/opencode/opencode-paths.d.ts +2 -0
- package/dist/opencode/opencode-paths.d.ts.map +1 -0
- package/dist/opencode/opencode-paths.js +7 -0
- package/dist/opencode/opencode-paths.js.map +1 -0
- package/dist/opencode/skill-loader.d.ts +6 -0
- package/dist/opencode/skill-loader.d.ts.map +1 -0
- package/dist/opencode/skill-loader.js +36 -0
- package/dist/opencode/skill-loader.js.map +1 -0
- package/package.json +7 -7
- package/.opencode/agent/github-reviewer.md +0 -77
- package/.opencode/agent/gitlab-reviewer.md +0 -77
- package/.opencode/agent/local-reviewer.md +0 -63
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Comment posting utilities for PR/MR reviews
|
|
3
|
+
*
|
|
4
|
+
* This module handles posting review comments to GitHub and GitLab platforms,
|
|
5
|
+
* including summary comments and inline code comments.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { formatSummaryComment, formatIssueComment } from './comment-formatter.js';
|
|
9
|
+
import { BOT_COMMENT_ID, createIssueFingerprint, findExistingSummaryComment, prepareIssuesForPosting, } from './comment-manager.js';
|
|
10
|
+
/**
|
|
11
|
+
* Post review comments to a PR/MR
|
|
12
|
+
*
|
|
13
|
+
* This function:
|
|
14
|
+
* 1. Fetches existing comments to prevent duplicates
|
|
15
|
+
* 2. Posts or updates a summary comment
|
|
16
|
+
* 3. Posts inline comments for CRITICAL/HIGH severity issues
|
|
17
|
+
* 4. Adds an "ai-reviewed" label
|
|
18
|
+
*/
|
|
19
|
+
export async function postReviewComments(platformClient, projectId, prNumber, summary, issues, changeSummary, platformData, lineValidator, createInlinePosition) {
|
|
20
|
+
console.log(chalk.gray('Fetching existing comments...\n'));
|
|
21
|
+
// Fetch existing comments to prevent duplicates
|
|
22
|
+
const [existingComments, existingInlineComments] = await Promise.all([
|
|
23
|
+
platformClient.getComments(projectId, prNumber),
|
|
24
|
+
platformClient.getInlineComments(projectId, prNumber),
|
|
25
|
+
]);
|
|
26
|
+
// Find our existing summary comment
|
|
27
|
+
const allComments = [
|
|
28
|
+
...existingComments.map((c) => ({ id: c.id, body: c.body })),
|
|
29
|
+
...existingInlineComments.map((c) => ({ id: c.id, body: c.body })),
|
|
30
|
+
];
|
|
31
|
+
const existingSummary = findExistingSummaryComment(existingComments.map((c) => ({ id: c.id, body: c.body })));
|
|
32
|
+
// Post or update summary comment
|
|
33
|
+
console.log(chalk.gray('Posting review summary...\n'));
|
|
34
|
+
const summaryComment = formatSummaryComment(summary, issues, BOT_COMMENT_ID, changeSummary);
|
|
35
|
+
if (existingSummary) {
|
|
36
|
+
await platformClient.updateComment(projectId, prNumber, existingSummary.id, summaryComment);
|
|
37
|
+
console.log(chalk.green('✓ Updated existing review summary'));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
await platformClient.createComment(projectId, prNumber, summaryComment);
|
|
41
|
+
console.log(chalk.green('✓ Posted new review summary'));
|
|
42
|
+
}
|
|
43
|
+
// Prepare issues for posting: filter to CRITICAL/HIGH, deduplicate, validate lines
|
|
44
|
+
const criticalHighCount = issues.filter((i) => i.severity === 'CRITICAL' || i.severity === 'HIGH').length;
|
|
45
|
+
const prepared = prepareIssuesForPosting(issues, allComments, (issue) => {
|
|
46
|
+
if (!issue.line || !lineValidator)
|
|
47
|
+
return false;
|
|
48
|
+
return lineValidator.isValidLine(issue.file, issue.line);
|
|
49
|
+
});
|
|
50
|
+
// Log diagnostic info about inline comment filtering
|
|
51
|
+
logInlineCommentDiagnostics(criticalHighCount, prepared.deduplicatedCount, prepared.inlineIssues.length, issues);
|
|
52
|
+
// Post inline comments for new CRITICAL/HIGH issues
|
|
53
|
+
if (!createInlinePosition) {
|
|
54
|
+
console.log(chalk.yellow(`⚠ Inline comments disabled (no position builder configured)\n`));
|
|
55
|
+
}
|
|
56
|
+
if (prepared.inlineIssues.length > 0 && createInlinePosition) {
|
|
57
|
+
const inlineComments = prepared.inlineIssues.map((issue) => ({
|
|
58
|
+
body: formatIssueComment(issue, createIssueFingerprint(issue)),
|
|
59
|
+
position: createInlinePosition(issue, platformData),
|
|
60
|
+
}));
|
|
61
|
+
await platformClient.createBulkInlineComments(projectId, prNumber, inlineComments);
|
|
62
|
+
}
|
|
63
|
+
// Add ai-reviewed label
|
|
64
|
+
await platformClient.addLabels(projectId, prNumber, ['ai-reviewed']);
|
|
65
|
+
console.log(chalk.green('✓ Review posted\n'));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Log diagnostic information about inline comment filtering
|
|
69
|
+
*/
|
|
70
|
+
function logInlineCommentDiagnostics(criticalHighCount, deduplicatedCount, inlineIssuesCount, allIssues) {
|
|
71
|
+
if (criticalHighCount > 0) {
|
|
72
|
+
console.log(chalk.gray(`Inline comments: ${criticalHighCount} CRITICAL/HIGH issue(s) found\n`));
|
|
73
|
+
if (deduplicatedCount > 0) {
|
|
74
|
+
console.log(chalk.gray(` - ${deduplicatedCount} already commented (skipped)\n`));
|
|
75
|
+
}
|
|
76
|
+
const issuesWithoutLines = allIssues.filter((i) => (i.severity === 'CRITICAL' || i.severity === 'HIGH') &&
|
|
77
|
+
(i.line === undefined || i.line === null)).length;
|
|
78
|
+
if (issuesWithoutLines > 0) {
|
|
79
|
+
console.log(chalk.gray(` - ${issuesWithoutLines} without line numbers (skipped)\n`));
|
|
80
|
+
}
|
|
81
|
+
const filteredByValidator = criticalHighCount - deduplicatedCount - issuesWithoutLines - inlineIssuesCount;
|
|
82
|
+
if (filteredByValidator > 0) {
|
|
83
|
+
console.log(chalk.gray(` - ${filteredByValidator} on lines not in diff (skipped)\n`));
|
|
84
|
+
}
|
|
85
|
+
if (inlineIssuesCount > 0) {
|
|
86
|
+
console.log(chalk.gray(` → ${inlineIssuesCount} will be posted as inline comments\n`));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.log(chalk.yellow(` → No inline comments to post (all filtered)\n`));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.log(chalk.gray(`No CRITICAL/HIGH issues - skipping inline comments (only summary posted)\n`));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=comment-poster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comment-poster.js","sourceRoot":"","sources":["../../src/lib/comment-poster.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comment-poster.test.d.ts","sourceRoot":"","sources":["../../src/lib/comment-poster.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for comment-poster.ts
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
5
|
+
import { postReviewComments } from './comment-poster.js';
|
|
6
|
+
// Mock dependencies
|
|
7
|
+
vi.mock('./comment-formatter.js', () => ({
|
|
8
|
+
formatSummaryComment: vi.fn((_summary, _issues, _botId, _changeSummary) => 'formatted summary'),
|
|
9
|
+
formatIssueComment: vi.fn((issue, _fingerprint) => `formatted issue: ${issue.title}`),
|
|
10
|
+
}));
|
|
11
|
+
vi.mock('./comment-manager.js', () => ({
|
|
12
|
+
BOT_COMMENT_ID: '<!-- DRS-REVIEW-BOT -->',
|
|
13
|
+
createIssueFingerprint: vi.fn((issue) => `fp-${issue.file}-${issue.line}`),
|
|
14
|
+
findExistingSummaryComment: vi.fn((comments) => {
|
|
15
|
+
return comments.find((c) => c.body.includes('<!-- DRS-REVIEW-BOT -->'));
|
|
16
|
+
}),
|
|
17
|
+
prepareIssuesForPosting: vi.fn((issues, allComments, lineValidator) => {
|
|
18
|
+
const criticalHigh = issues.filter((i) => i.severity === 'CRITICAL' || i.severity === 'HIGH');
|
|
19
|
+
const inlineIssues = criticalHigh.filter((i) => i.line && lineValidator(i));
|
|
20
|
+
return {
|
|
21
|
+
inlineIssues,
|
|
22
|
+
deduplicatedCount: 0,
|
|
23
|
+
};
|
|
24
|
+
}),
|
|
25
|
+
}));
|
|
26
|
+
describe('comment-poster', () => {
|
|
27
|
+
let mockPlatformClient;
|
|
28
|
+
let mockSummary;
|
|
29
|
+
let mockIssues;
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
mockPlatformClient = {
|
|
32
|
+
getPullRequest: vi.fn(),
|
|
33
|
+
getChangedFiles: vi.fn(),
|
|
34
|
+
getComments: vi.fn().mockResolvedValue([]),
|
|
35
|
+
getInlineComments: vi.fn().mockResolvedValue([]),
|
|
36
|
+
createComment: vi.fn().mockResolvedValue({ id: '1' }),
|
|
37
|
+
updateComment: vi.fn().mockResolvedValue({ id: '1' }),
|
|
38
|
+
createBulkInlineComments: vi.fn().mockResolvedValue([]),
|
|
39
|
+
addLabels: vi.fn().mockResolvedValue(undefined),
|
|
40
|
+
};
|
|
41
|
+
mockSummary = {
|
|
42
|
+
issuesFound: 3,
|
|
43
|
+
filesReviewed: 2,
|
|
44
|
+
bySeverity: {
|
|
45
|
+
CRITICAL: 1,
|
|
46
|
+
HIGH: 1,
|
|
47
|
+
MEDIUM: 1,
|
|
48
|
+
LOW: 0,
|
|
49
|
+
},
|
|
50
|
+
byCategory: {
|
|
51
|
+
SECURITY: 1,
|
|
52
|
+
QUALITY: 1,
|
|
53
|
+
STYLE: 1,
|
|
54
|
+
PERFORMANCE: 0,
|
|
55
|
+
DOCUMENTATION: 0,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
mockIssues = [
|
|
59
|
+
{
|
|
60
|
+
severity: 'CRITICAL',
|
|
61
|
+
category: 'SECURITY',
|
|
62
|
+
title: 'SQL injection vulnerability',
|
|
63
|
+
problem: 'SQL injection vulnerability detected',
|
|
64
|
+
solution: 'Use parameterized queries',
|
|
65
|
+
file: 'src/api.ts',
|
|
66
|
+
line: 42,
|
|
67
|
+
agent: 'security',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
severity: 'HIGH',
|
|
71
|
+
category: 'QUALITY',
|
|
72
|
+
title: 'Complex function',
|
|
73
|
+
problem: 'Function is too complex',
|
|
74
|
+
solution: 'Refactor into smaller functions',
|
|
75
|
+
file: 'src/utils.ts',
|
|
76
|
+
line: 10,
|
|
77
|
+
agent: 'quality',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
severity: 'MEDIUM',
|
|
81
|
+
category: 'STYLE',
|
|
82
|
+
title: 'Missing type annotation',
|
|
83
|
+
problem: 'Variable lacks type annotation',
|
|
84
|
+
solution: 'Add explicit type annotation',
|
|
85
|
+
file: 'src/types.ts',
|
|
86
|
+
line: 5,
|
|
87
|
+
agent: 'style',
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
});
|
|
91
|
+
describe('postReviewComments', () => {
|
|
92
|
+
it('should create a new summary comment when none exists', async () => {
|
|
93
|
+
await postReviewComments(mockPlatformClient, 'owner/repo', 123, mockSummary, mockIssues, undefined, {}, undefined, undefined);
|
|
94
|
+
expect(mockPlatformClient.createComment).toHaveBeenCalledWith('owner/repo', 123, 'formatted summary');
|
|
95
|
+
expect(mockPlatformClient.updateComment).not.toHaveBeenCalled();
|
|
96
|
+
});
|
|
97
|
+
it('should update existing summary comment', async () => {
|
|
98
|
+
const existingComment = {
|
|
99
|
+
id: '999',
|
|
100
|
+
body: '<!-- DRS-REVIEW-BOT --> Old summary',
|
|
101
|
+
};
|
|
102
|
+
mockPlatformClient.getComments = vi.fn().mockResolvedValue([existingComment]);
|
|
103
|
+
await postReviewComments(mockPlatformClient, 'owner/repo', 123, mockSummary, mockIssues, undefined, {}, undefined, undefined);
|
|
104
|
+
expect(mockPlatformClient.updateComment).toHaveBeenCalledWith('owner/repo', 123, '999', 'formatted summary');
|
|
105
|
+
expect(mockPlatformClient.createComment).not.toHaveBeenCalled();
|
|
106
|
+
});
|
|
107
|
+
it('should post inline comments for CRITICAL/HIGH issues', async () => {
|
|
108
|
+
const mockLineValidator = {
|
|
109
|
+
isValidLine: vi.fn((_file, _line) => true),
|
|
110
|
+
};
|
|
111
|
+
const mockCreateInlinePosition = vi.fn((issue) => ({
|
|
112
|
+
path: issue.file,
|
|
113
|
+
line: issue.line,
|
|
114
|
+
side: 'RIGHT',
|
|
115
|
+
}));
|
|
116
|
+
await postReviewComments(mockPlatformClient, 'owner/repo', 123, mockSummary, mockIssues, undefined, {}, mockLineValidator, mockCreateInlinePosition);
|
|
117
|
+
expect(mockPlatformClient.createBulkInlineComments).toHaveBeenCalledWith('owner/repo', 123, expect.arrayContaining([
|
|
118
|
+
expect.objectContaining({
|
|
119
|
+
body: expect.stringContaining('SQL injection vulnerability'),
|
|
120
|
+
position: expect.objectContaining({ path: 'src/api.ts', line: 42 }),
|
|
121
|
+
}),
|
|
122
|
+
expect.objectContaining({
|
|
123
|
+
body: expect.stringContaining('Complex function'),
|
|
124
|
+
position: expect.objectContaining({ path: 'src/utils.ts', line: 10 }),
|
|
125
|
+
}),
|
|
126
|
+
]));
|
|
127
|
+
});
|
|
128
|
+
it('should not post inline comments for MEDIUM/LOW issues', async () => {
|
|
129
|
+
const lowSeverityIssues = [
|
|
130
|
+
{
|
|
131
|
+
severity: 'MEDIUM',
|
|
132
|
+
category: 'STYLE',
|
|
133
|
+
title: 'Medium issue',
|
|
134
|
+
problem: 'Medium severity issue',
|
|
135
|
+
solution: 'Fix this issue',
|
|
136
|
+
file: 'src/test.ts',
|
|
137
|
+
line: 1,
|
|
138
|
+
agent: 'style',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
severity: 'LOW',
|
|
142
|
+
category: 'STYLE',
|
|
143
|
+
title: 'Low issue',
|
|
144
|
+
problem: 'Low severity issue',
|
|
145
|
+
solution: 'Fix this issue',
|
|
146
|
+
file: 'src/test.ts',
|
|
147
|
+
line: 2,
|
|
148
|
+
agent: 'style',
|
|
149
|
+
},
|
|
150
|
+
];
|
|
151
|
+
const mockLineValidator = {
|
|
152
|
+
isValidLine: vi.fn(() => true),
|
|
153
|
+
};
|
|
154
|
+
const mockCreateInlinePosition = vi.fn((issue) => ({
|
|
155
|
+
path: issue.file,
|
|
156
|
+
line: issue.line,
|
|
157
|
+
side: 'RIGHT',
|
|
158
|
+
}));
|
|
159
|
+
await postReviewComments(mockPlatformClient, 'owner/repo', 123, {
|
|
160
|
+
issuesFound: 2,
|
|
161
|
+
filesReviewed: 1,
|
|
162
|
+
bySeverity: { CRITICAL: 0, HIGH: 0, MEDIUM: 1, LOW: 1 },
|
|
163
|
+
byCategory: { SECURITY: 0, QUALITY: 0, STYLE: 2, PERFORMANCE: 0, DOCUMENTATION: 0 },
|
|
164
|
+
}, lowSeverityIssues, undefined, {}, mockLineValidator, mockCreateInlinePosition);
|
|
165
|
+
// Should not create inline comments for MEDIUM/LOW
|
|
166
|
+
expect(mockPlatformClient.createBulkInlineComments).not.toHaveBeenCalled();
|
|
167
|
+
});
|
|
168
|
+
it('should skip inline comments when no line validator provided', async () => {
|
|
169
|
+
const mockCreateInlinePosition = vi.fn((issue) => ({
|
|
170
|
+
path: issue.file,
|
|
171
|
+
line: issue.line,
|
|
172
|
+
side: 'RIGHT',
|
|
173
|
+
}));
|
|
174
|
+
await postReviewComments(mockPlatformClient, 'owner/repo', 123, mockSummary, mockIssues, undefined, {}, undefined, // No line validator
|
|
175
|
+
mockCreateInlinePosition);
|
|
176
|
+
// Should not create inline comments
|
|
177
|
+
expect(mockPlatformClient.createBulkInlineComments).not.toHaveBeenCalled();
|
|
178
|
+
});
|
|
179
|
+
it('should skip inline comments when no position builder provided', async () => {
|
|
180
|
+
const mockLineValidator = {
|
|
181
|
+
isValidLine: vi.fn(() => true),
|
|
182
|
+
};
|
|
183
|
+
await postReviewComments(mockPlatformClient, 'owner/repo', 123, mockSummary, mockIssues, undefined, {}, mockLineValidator, undefined // No position builder
|
|
184
|
+
);
|
|
185
|
+
// Should not create inline comments
|
|
186
|
+
expect(mockPlatformClient.createBulkInlineComments).not.toHaveBeenCalled();
|
|
187
|
+
});
|
|
188
|
+
it('should add ai-reviewed label', async () => {
|
|
189
|
+
await postReviewComments(mockPlatformClient, 'owner/repo', 123, mockSummary, mockIssues, undefined, {}, undefined, undefined);
|
|
190
|
+
expect(mockPlatformClient.addLabels).toHaveBeenCalledWith('owner/repo', 123, ['ai-reviewed']);
|
|
191
|
+
});
|
|
192
|
+
it('should fetch both regular and inline comments', async () => {
|
|
193
|
+
await postReviewComments(mockPlatformClient, 'owner/repo', 123, mockSummary, mockIssues, undefined, {}, undefined, undefined);
|
|
194
|
+
expect(mockPlatformClient.getComments).toHaveBeenCalledWith('owner/repo', 123);
|
|
195
|
+
expect(mockPlatformClient.getInlineComments).toHaveBeenCalledWith('owner/repo', 123);
|
|
196
|
+
});
|
|
197
|
+
it('should include change summary in formatted comment', async () => {
|
|
198
|
+
const mockChangeSummary = {
|
|
199
|
+
type: 'feature',
|
|
200
|
+
subsystems: ['api'],
|
|
201
|
+
complexity: 'medium',
|
|
202
|
+
riskLevel: 'low',
|
|
203
|
+
linesAdded: 50,
|
|
204
|
+
linesRemoved: 20,
|
|
205
|
+
filesChanged: 5,
|
|
206
|
+
description: 'Added new feature',
|
|
207
|
+
};
|
|
208
|
+
await postReviewComments(mockPlatformClient, 'owner/repo', 123, mockSummary, mockIssues, mockChangeSummary, {}, undefined, undefined);
|
|
209
|
+
// Should be called with change summary
|
|
210
|
+
const { formatSummaryComment } = await import('./comment-formatter.js');
|
|
211
|
+
expect(formatSummaryComment).toHaveBeenCalledWith(mockSummary, mockIssues, expect.any(String), mockChangeSummary);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
//# sourceMappingURL=comment-poster.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comment-poster.test.js","sourceRoot":"","sources":["../../src/lib/comment-poster.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* 5. (Falls through to opencode.jsonc, not tested here)
|
|
10
10
|
*/
|
|
11
11
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
12
|
-
import { getModelOverrides, normalizeAgentConfig, getAgentNames, } from './config.js';
|
|
12
|
+
import { getModelOverrides, getUnifiedModelOverride, normalizeAgentConfig, getAgentNames, } from './config.js';
|
|
13
13
|
describe('Model Override Precedence', () => {
|
|
14
14
|
const originalEnv = process.env;
|
|
15
15
|
beforeEach(() => {
|
|
@@ -20,29 +20,38 @@ describe('Model Override Precedence', () => {
|
|
|
20
20
|
delete process.env.REVIEW_AGENT_QUALITY_MODEL;
|
|
21
21
|
delete process.env.REVIEW_AGENT_STYLE_MODEL;
|
|
22
22
|
delete process.env.REVIEW_AGENT_PERFORMANCE_MODEL;
|
|
23
|
+
delete process.env.REVIEW_UNIFIED_MODEL;
|
|
23
24
|
});
|
|
24
25
|
afterEach(() => {
|
|
25
26
|
process.env = originalEnv;
|
|
26
27
|
});
|
|
27
|
-
const createMockConfig = (overrides) =>
|
|
28
|
-
|
|
29
|
-
gitlab: { url: '', token: '' },
|
|
30
|
-
github: { token: '' },
|
|
31
|
-
review: {
|
|
28
|
+
const createMockConfig = (overrides) => {
|
|
29
|
+
const baseReview = {
|
|
32
30
|
agents: ['security', 'quality', 'style', 'performance'],
|
|
33
|
-
autoReview: true,
|
|
34
|
-
reviewOnMention: true,
|
|
35
|
-
reviewOnLabel: [],
|
|
36
31
|
ignorePatterns: [],
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
32
|
+
};
|
|
33
|
+
// Only set defaultModel if no overrides provided at all (to maintain backward compatibility)
|
|
34
|
+
// If overrides are provided, only set defaultModel if explicitly included in overrides
|
|
35
|
+
if (!overrides) {
|
|
36
|
+
baseReview.defaultModel = 'anthropic/claude-sonnet-4-5-20250929';
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
opencode: {},
|
|
40
|
+
gitlab: { url: '', token: '' },
|
|
41
|
+
github: { token: '' },
|
|
42
|
+
review: {
|
|
43
|
+
...baseReview,
|
|
44
|
+
...overrides,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
describe('Test 1: Default model always set', () => {
|
|
49
|
+
it('should return overrides based on defaultModel', () => {
|
|
43
50
|
const config = createMockConfig();
|
|
44
51
|
const overrides = getModelOverrides(config);
|
|
45
|
-
|
|
52
|
+
// defaultModel is now required, so all agents get the default
|
|
53
|
+
// Only review/<agent> format is used (matching how agents are invoked)
|
|
54
|
+
expect(overrides['review/security']).toBe('anthropic/claude-sonnet-4-5-20250929');
|
|
46
55
|
});
|
|
47
56
|
});
|
|
48
57
|
describe('Test 2: DRS defaultModel only', () => {
|
|
@@ -53,13 +62,9 @@ describe('Model Override Precedence', () => {
|
|
|
53
62
|
});
|
|
54
63
|
const overrides = getModelOverrides(config);
|
|
55
64
|
expect(overrides).toEqual({
|
|
56
|
-
security: 'zhipuai/glm-4.7',
|
|
57
65
|
'review/security': 'zhipuai/glm-4.7',
|
|
58
|
-
quality: 'zhipuai/glm-4.7',
|
|
59
66
|
'review/quality': 'zhipuai/glm-4.7',
|
|
60
|
-
style: 'zhipuai/glm-4.7',
|
|
61
67
|
'review/style': 'zhipuai/glm-4.7',
|
|
62
|
-
performance: 'zhipuai/glm-4.7',
|
|
63
68
|
'review/performance': 'zhipuai/glm-4.7',
|
|
64
69
|
});
|
|
65
70
|
});
|
|
@@ -77,13 +82,9 @@ describe('Model Override Precedence', () => {
|
|
|
77
82
|
});
|
|
78
83
|
const overrides = getModelOverrides(config);
|
|
79
84
|
expect(overrides).toEqual({
|
|
80
|
-
security: 'anthropic/claude-opus-4-5-20251101',
|
|
81
85
|
'review/security': 'anthropic/claude-opus-4-5-20251101',
|
|
82
|
-
quality: 'zhipuai/glm-4.7',
|
|
83
86
|
'review/quality': 'zhipuai/glm-4.7',
|
|
84
|
-
style: 'anthropic/claude-sonnet-4-5-20250929',
|
|
85
87
|
'review/style': 'anthropic/claude-sonnet-4-5-20250929',
|
|
86
|
-
performance: 'zhipuai/glm-4.7',
|
|
87
88
|
'review/performance': 'zhipuai/glm-4.7',
|
|
88
89
|
});
|
|
89
90
|
});
|
|
@@ -96,9 +97,7 @@ describe('Model Override Precedence', () => {
|
|
|
96
97
|
});
|
|
97
98
|
const overrides = getModelOverrides(config);
|
|
98
99
|
expect(overrides).toEqual({
|
|
99
|
-
security: 'provider/model-from-env',
|
|
100
100
|
'review/security': 'provider/model-from-env',
|
|
101
|
-
quality: 'provider/model-from-env',
|
|
102
101
|
'review/quality': 'provider/model-from-env',
|
|
103
102
|
});
|
|
104
103
|
});
|
|
@@ -109,7 +108,7 @@ describe('Model Override Precedence', () => {
|
|
|
109
108
|
agents: ['security'],
|
|
110
109
|
});
|
|
111
110
|
const overrides = getModelOverrides(config);
|
|
112
|
-
expect(overrides
|
|
111
|
+
expect(overrides['review/security']).toBe('zhipuai/config-model');
|
|
113
112
|
});
|
|
114
113
|
});
|
|
115
114
|
describe('Test 5: Environment REVIEW_AGENT_<NAME>_MODEL', () => {
|
|
@@ -121,9 +120,7 @@ describe('Model Override Precedence', () => {
|
|
|
121
120
|
});
|
|
122
121
|
const overrides = getModelOverrides(config);
|
|
123
122
|
expect(overrides).toEqual({
|
|
124
|
-
security: 'provider/security-from-env',
|
|
125
123
|
'review/security': 'provider/security-from-env',
|
|
126
|
-
quality: 'zhipuai/glm-4.7',
|
|
127
124
|
'review/quality': 'zhipuai/glm-4.7',
|
|
128
125
|
});
|
|
129
126
|
});
|
|
@@ -131,9 +128,11 @@ describe('Model Override Precedence', () => {
|
|
|
131
128
|
process.env.REVIEW_AGENT_CUSTOM_SECURITY_MODEL = 'provider/custom-model';
|
|
132
129
|
const config = createMockConfig({
|
|
133
130
|
agents: ['custom-security'],
|
|
131
|
+
defaultModel: 'zhipuai/glm-4.7',
|
|
134
132
|
});
|
|
135
133
|
const overrides = getModelOverrides(config);
|
|
136
|
-
|
|
134
|
+
// Env var takes precedence over defaultModel
|
|
135
|
+
expect(overrides['review/custom-security']).toBe('provider/custom-model');
|
|
137
136
|
});
|
|
138
137
|
});
|
|
139
138
|
describe('Test 6: Complete precedence chain', () => {
|
|
@@ -148,11 +147,11 @@ describe('Model Override Precedence', () => {
|
|
|
148
147
|
const overrides = getModelOverrides(config);
|
|
149
148
|
// Precedence verification:
|
|
150
149
|
// security: per-agent config wins
|
|
151
|
-
expect(overrides
|
|
150
|
+
expect(overrides['review/security']).toBe('anthropic/security-config');
|
|
152
151
|
// quality: env agent var wins over config default
|
|
153
|
-
expect(overrides
|
|
152
|
+
expect(overrides['review/quality']).toBe('provider/quality-env');
|
|
154
153
|
// style: config default wins over env default
|
|
155
|
-
expect(overrides
|
|
154
|
+
expect(overrides['review/style']).toBe('zhipuai/default-config');
|
|
156
155
|
});
|
|
157
156
|
});
|
|
158
157
|
describe('Test 7: Mixed agent formats', () => {
|
|
@@ -167,10 +166,10 @@ describe('Model Override Precedence', () => {
|
|
|
167
166
|
],
|
|
168
167
|
});
|
|
169
168
|
const overrides = getModelOverrides(config);
|
|
170
|
-
expect(overrides
|
|
171
|
-
expect(overrides
|
|
172
|
-
expect(overrides
|
|
173
|
-
expect(overrides
|
|
169
|
+
expect(overrides['review/security']).toBe('zhipuai/glm-4.7');
|
|
170
|
+
expect(overrides['review/quality']).toBe('anthropic/claude-opus-4-5-20251101');
|
|
171
|
+
expect(overrides['review/style']).toBe('zhipuai/glm-4.7');
|
|
172
|
+
expect(overrides['review/performance']).toBe('zhipuai/glm-4.7');
|
|
174
173
|
});
|
|
175
174
|
});
|
|
176
175
|
describe('Agent name normalization', () => {
|
|
@@ -194,6 +193,33 @@ describe('Model Override Precedence', () => {
|
|
|
194
193
|
expect(names).toEqual(['security', 'quality', 'style']);
|
|
195
194
|
});
|
|
196
195
|
});
|
|
196
|
+
describe('Unified reviewer model overrides', () => {
|
|
197
|
+
it('should use unified model from config', () => {
|
|
198
|
+
const config = createMockConfig({
|
|
199
|
+
defaultModel: 'anthropic/claude-sonnet-4-5-20250929',
|
|
200
|
+
unified: {
|
|
201
|
+
model: 'provider/unified-config',
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
const overrides = getUnifiedModelOverride(config);
|
|
205
|
+
expect(overrides['review/unified-reviewer']).toBe('provider/unified-config');
|
|
206
|
+
});
|
|
207
|
+
it('should fall back to env REVIEW_UNIFIED_MODEL when config missing', () => {
|
|
208
|
+
process.env.REVIEW_UNIFIED_MODEL = 'provider/unified-env';
|
|
209
|
+
const config = createMockConfig({
|
|
210
|
+
defaultModel: 'provider/default-model',
|
|
211
|
+
});
|
|
212
|
+
const overrides = getUnifiedModelOverride(config);
|
|
213
|
+
expect(overrides['review/unified-reviewer']).toBe('provider/unified-env');
|
|
214
|
+
});
|
|
215
|
+
it('should fall back to review.defaultModel when unified model missing', () => {
|
|
216
|
+
const config = createMockConfig({
|
|
217
|
+
defaultModel: 'provider/default-model',
|
|
218
|
+
});
|
|
219
|
+
const overrides = getUnifiedModelOverride(config);
|
|
220
|
+
expect(overrides['review/unified-reviewer']).toBe('provider/default-model');
|
|
221
|
+
});
|
|
222
|
+
});
|
|
197
223
|
describe('Edge cases', () => {
|
|
198
224
|
it('should handle empty agents array', () => {
|
|
199
225
|
const config = createMockConfig({
|
|
@@ -203,21 +229,25 @@ describe('Model Override Precedence', () => {
|
|
|
203
229
|
const overrides = getModelOverrides(config);
|
|
204
230
|
expect(overrides).toEqual({});
|
|
205
231
|
});
|
|
206
|
-
it('should
|
|
232
|
+
it('should apply defaultModel to agents without explicit model', () => {
|
|
207
233
|
const config = createMockConfig({
|
|
208
234
|
agents: [{ name: 'security' }, { name: 'quality' }],
|
|
235
|
+
defaultModel: 'test/default-model',
|
|
209
236
|
});
|
|
210
237
|
const overrides = getModelOverrides(config);
|
|
211
|
-
|
|
238
|
+
// defaultModel is now always applied
|
|
239
|
+
expect(overrides['review/security']).toBe('test/default-model');
|
|
240
|
+
expect(overrides['review/quality']).toBe('test/default-model');
|
|
212
241
|
});
|
|
213
|
-
it('should create
|
|
242
|
+
it('should only create review/ prefixed keys (matching how agents are invoked)', () => {
|
|
214
243
|
const config = createMockConfig({
|
|
215
244
|
defaultModel: 'test/model',
|
|
216
245
|
agents: ['security'],
|
|
217
246
|
});
|
|
218
247
|
const overrides = getModelOverrides(config);
|
|
219
|
-
|
|
248
|
+
// Only review/<agent> format is used
|
|
220
249
|
expect(overrides['review/security']).toBe('test/model');
|
|
250
|
+
expect(Object.keys(overrides)).toEqual(['review/security']);
|
|
221
251
|
});
|
|
222
252
|
});
|
|
223
253
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-model-overrides.test.js","sourceRoot":"","sources":["../../src/lib/config-model-overrides.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,aAAa,GAEd,MAAM,aAAa,CAAC;AAErB,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;IAEhC,UAAU,CAAC,GAAG,EAAE;QACd,qCAAqC;QACrC,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACxC,OAAO,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;QAC/C,OAAO,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;QAC9C,OAAO,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;QAC5C,OAAO,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"config-model-overrides.test.js","sourceRoot":"","sources":["../../src/lib/config-model-overrides.test.ts"],"names":[],"mappings":"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"}
|