diffintel 0.2.1 → 0.3.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/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/explain.d.ts +1 -0
- package/dist/commands/explain.js +37 -6
- package/dist/commands/explain.js.map +1 -1
- package/dist/explain/ast-diff.d.ts +2 -9
- package/dist/explain/ast-diff.js +8 -74
- package/dist/explain/ast-diff.js.map +1 -1
- package/dist/explain/generic-extractor.d.ts +13 -0
- package/dist/explain/generic-extractor.js +85 -0
- package/dist/explain/generic-extractor.js.map +1 -0
- package/dist/explain/html-report.js +127 -7
- package/dist/explain/html-report.js.map +1 -1
- package/dist/explain/language-configs.d.ts +31 -0
- package/dist/explain/language-configs.js +514 -0
- package/dist/explain/language-configs.js.map +1 -0
- package/dist/explain/llm-explain.js +5 -1
- package/dist/explain/llm-explain.js.map +1 -1
- package/dist/explain/markdown-summary.d.ts +5 -0
- package/dist/explain/markdown-summary.js +98 -0
- package/dist/explain/markdown-summary.js.map +1 -0
- package/dist/explain/types.d.ts +1 -0
- package/dist/parsing/index.d.ts +1 -1
- package/dist/parsing/index.js +3 -1
- package/dist/parsing/index.js.map +1 -1
- package/dist/parsing/parser.d.ts +4 -0
- package/dist/parsing/parser.js +69 -2
- package/dist/parsing/parser.js.map +1 -1
- package/package.json +12 -1
package/dist/cli.js
CHANGED
|
@@ -16,6 +16,7 @@ commander_1.program
|
|
|
16
16
|
.option("--base <ref>", "Base ref to diff from (default: origin/main)")
|
|
17
17
|
.option("--head <ref>", "Head ref to diff to (default: HEAD)")
|
|
18
18
|
.option("--out <file>", "Output HTML file path (default: explain-report.html)")
|
|
19
|
+
.option("--summary <file>", "Output markdown summary file path (default: <out>.md)")
|
|
19
20
|
.action(async (opts) => {
|
|
20
21
|
require("dotenv").config();
|
|
21
22
|
const { run } = require("./commands/explain");
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,mEAAkC;AAElC,mBAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,wDAAwD,CAAC;KACrE,OAAO,CAAC,sBAAG,CAAC,OAAO,CAAC,CAAC;AAExB,mBAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,cAAc,EAAE,8CAA8C,CAAC;KACtE,MAAM,CAAC,cAAc,EAAE,qCAAqC,CAAC;KAC7D,MAAM,CAAC,cAAc,EAAE,sDAAsD,CAAC;KAC9E,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC;AAEL,mBAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,mEAAkC;AAElC,mBAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,wDAAwD,CAAC;KACrE,OAAO,CAAC,sBAAG,CAAC,OAAO,CAAC,CAAC;AAExB,mBAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,cAAc,EAAE,8CAA8C,CAAC;KACtE,MAAM,CAAC,cAAc,EAAE,qCAAqC,CAAC;KAC7D,MAAM,CAAC,cAAc,EAAE,sDAAsD,CAAC;KAC9E,MAAM,CAAC,kBAAkB,EAAE,uDAAuD,CAAC;KACnF,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC;AAEL,mBAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/dist/commands/explain.js
CHANGED
|
@@ -9,14 +9,12 @@ const git_diff_1 = require("../explain/git-diff");
|
|
|
9
9
|
const ast_diff_1 = require("../explain/ast-diff");
|
|
10
10
|
const llm_explain_1 = require("../explain/llm-explain");
|
|
11
11
|
const html_report_1 = require("../explain/html-report");
|
|
12
|
+
const markdown_summary_1 = require("../explain/markdown-summary");
|
|
12
13
|
async function run(opts) {
|
|
13
14
|
const baseRef = opts.base || "origin/main";
|
|
14
15
|
const headRef = opts.head || "HEAD";
|
|
15
16
|
const outFile = opts.out || "explain-report.html";
|
|
16
|
-
|
|
17
|
-
console.error("Error: ANTHROPIC_API_KEY environment variable is required.");
|
|
18
|
-
return 1;
|
|
19
|
-
}
|
|
17
|
+
const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
|
|
20
18
|
try {
|
|
21
19
|
console.error(`Analyzing diff: ${baseRef}...${headRef}`);
|
|
22
20
|
const { files: fileDiffs, rawDiff } = (0, git_diff_1.getDiff)(baseRef, headRef);
|
|
@@ -31,10 +29,25 @@ async function run(opts) {
|
|
|
31
29
|
return analysis;
|
|
32
30
|
});
|
|
33
31
|
const totalChanges = fileAnalyses.reduce((sum, f) => sum + f.structuralChanges.length, 0);
|
|
34
|
-
console.error(`Detected ${totalChanges} structural change(s). Calling LLM...`);
|
|
35
|
-
const explanation = await (0, llm_explain_1.explainChanges)(fileAnalyses, rawDiff);
|
|
36
32
|
const totalAdditions = fileDiffs.reduce((sum, f) => sum + f.additions, 0);
|
|
37
33
|
const totalDeletions = fileDiffs.reduce((sum, f) => sum + f.deletions, 0);
|
|
34
|
+
let explanation;
|
|
35
|
+
if (hasApiKey) {
|
|
36
|
+
console.error(`Detected ${totalChanges} structural change(s). Calling LLM...`);
|
|
37
|
+
explanation = await (0, llm_explain_1.explainChanges)(fileAnalyses, rawDiff);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.error(`Detected ${totalChanges} structural change(s). No API key — generating AST-only report.`);
|
|
41
|
+
explanation = {
|
|
42
|
+
title: buildAutoTitle(fileDiffs.length, totalAdditions, totalDeletions),
|
|
43
|
+
description: "",
|
|
44
|
+
impact: [],
|
|
45
|
+
fixes: [],
|
|
46
|
+
risks: [],
|
|
47
|
+
fileExplanations: [],
|
|
48
|
+
tokenUsage: { input: 0, output: 0 },
|
|
49
|
+
};
|
|
50
|
+
}
|
|
38
51
|
const report = {
|
|
39
52
|
generatedAt: new Date().toISOString(),
|
|
40
53
|
baseRef,
|
|
@@ -49,6 +62,10 @@ async function run(opts) {
|
|
|
49
62
|
};
|
|
50
63
|
const html = (0, html_report_1.renderReport)(report);
|
|
51
64
|
fs_1.default.writeFileSync(outFile, html, "utf-8");
|
|
65
|
+
// Generate markdown summary alongside HTML
|
|
66
|
+
const summaryFile = opts.summary || outFile.replace(/\.html$/, ".md");
|
|
67
|
+
const markdown = (0, markdown_summary_1.renderMarkdownSummary)(report);
|
|
68
|
+
fs_1.default.writeFileSync(summaryFile, markdown, "utf-8");
|
|
52
69
|
console.error(`\n${explanation.title}`);
|
|
53
70
|
console.error(`${fileDiffs.length} files | +${totalAdditions} -${totalDeletions}`);
|
|
54
71
|
if (explanation.fixes.length > 0) {
|
|
@@ -58,6 +75,7 @@ async function run(opts) {
|
|
|
58
75
|
console.error(`Risks: ${explanation.risks.map((r) => `[${r.level}] ${r.description}`).join("; ")}`);
|
|
59
76
|
}
|
|
60
77
|
console.error(`\nReport: ${outFile}`);
|
|
78
|
+
console.error(`Summary: ${summaryFile}`);
|
|
61
79
|
return 0;
|
|
62
80
|
}
|
|
63
81
|
catch (err) {
|
|
@@ -65,4 +83,17 @@ async function run(opts) {
|
|
|
65
83
|
return 1;
|
|
66
84
|
}
|
|
67
85
|
}
|
|
86
|
+
function buildAutoTitle(fileCount, additions, deletions) {
|
|
87
|
+
const parts = [];
|
|
88
|
+
if (additions > 0 && deletions > 0)
|
|
89
|
+
parts.push("Modified");
|
|
90
|
+
else if (additions > 0)
|
|
91
|
+
parts.push("Added");
|
|
92
|
+
else if (deletions > 0)
|
|
93
|
+
parts.push("Removed");
|
|
94
|
+
else
|
|
95
|
+
parts.push("Changed");
|
|
96
|
+
parts.push(`${fileCount} file${fileCount !== 1 ? "s" : ""}`);
|
|
97
|
+
return `${parts.join(" ")} (+${additions} -${deletions})`;
|
|
98
|
+
}
|
|
68
99
|
//# sourceMappingURL=explain.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/commands/explain.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/commands/explain.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import { FileDiff, FileAnalysis
|
|
2
|
-
interface Declaration {
|
|
3
|
-
name: string;
|
|
4
|
-
type: ChangeType;
|
|
5
|
-
text: string;
|
|
6
|
-
startLine: number;
|
|
7
|
-
}
|
|
1
|
+
import { FileDiff, FileAnalysis } from "./types";
|
|
8
2
|
export declare function analyzeFile(diff: FileDiff): FileAnalysis;
|
|
9
|
-
export declare function extractDeclarations(source: string, ext: string): Declaration[];
|
|
10
|
-
export {};
|
|
3
|
+
export declare function extractDeclarations(source: string, ext: string): import("./generic-extractor").Declaration[];
|
package/dist/explain/ast-diff.js
CHANGED
|
@@ -6,11 +6,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.analyzeFile = analyzeFile;
|
|
7
7
|
exports.extractDeclarations = extractDeclarations;
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const generic_extractor_1 = require("./generic-extractor");
|
|
10
|
+
const language_configs_1 = require("./language-configs");
|
|
9
11
|
const parser_1 = require("../parsing/parser");
|
|
10
|
-
const SUPPORTED_EXTS = new Set([".js", ".ts", ".tsx", ".jsx"]);
|
|
11
12
|
function analyzeFile(diff) {
|
|
12
13
|
const ext = path_1.default.extname(diff.path);
|
|
13
|
-
|
|
14
|
+
const config = (0, language_configs_1.getConfigForExtension)(ext);
|
|
15
|
+
const parseable = (0, parser_1.hasLanguageForExt)(ext);
|
|
16
|
+
// If no config and not parseable, return without structural analysis
|
|
17
|
+
if (!config && !parseable) {
|
|
14
18
|
return {
|
|
15
19
|
path: diff.path,
|
|
16
20
|
status: diff.status,
|
|
@@ -21,7 +25,7 @@ function analyzeFile(diff) {
|
|
|
21
25
|
rawDiff: diff.hunks,
|
|
22
26
|
};
|
|
23
27
|
}
|
|
24
|
-
const language = ext.replace(".", "");
|
|
28
|
+
const language = config?.id || ext.replace(".", "");
|
|
25
29
|
const structuralChanges = [];
|
|
26
30
|
// Extract base declarations for context (what existed before this change)
|
|
27
31
|
const baseDecls = diff.oldContent ? extractDeclarations(diff.oldContent, ext) : [];
|
|
@@ -99,76 +103,6 @@ function analyzeFile(diff) {
|
|
|
99
103
|
};
|
|
100
104
|
}
|
|
101
105
|
function extractDeclarations(source, ext) {
|
|
102
|
-
|
|
103
|
-
return [];
|
|
104
|
-
const { tree } = (0, parser_1.parseSource)(source, ext);
|
|
105
|
-
const decls = [];
|
|
106
|
-
const root = tree.rootNode;
|
|
107
|
-
for (let i = 0; i < root.childCount; i++) {
|
|
108
|
-
const node = root.child(i);
|
|
109
|
-
const extracted = extractFromNode(node);
|
|
110
|
-
if (extracted) {
|
|
111
|
-
decls.push(...extracted);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return decls;
|
|
115
|
-
}
|
|
116
|
-
function extractFromNode(node) {
|
|
117
|
-
const type = node.type;
|
|
118
|
-
if (type === "function_declaration") {
|
|
119
|
-
const name = node.childForFieldName("name")?.text || "<anonymous>";
|
|
120
|
-
return [{ name, type: "function", text: node.text, startLine: node.startPosition.row + 1 }];
|
|
121
|
-
}
|
|
122
|
-
if (type === "class_declaration") {
|
|
123
|
-
const name = node.childForFieldName("name")?.text || "<anonymous>";
|
|
124
|
-
return [{ name, type: "class", text: node.text, startLine: node.startPosition.row + 1 }];
|
|
125
|
-
}
|
|
126
|
-
if (type === "import_statement") {
|
|
127
|
-
const source = node.childForFieldName("source")?.text || node.text;
|
|
128
|
-
return [{ name: source, type: "import", text: node.text, startLine: node.startPosition.row + 1 }];
|
|
129
|
-
}
|
|
130
|
-
if (type === "export_statement") {
|
|
131
|
-
// Named export with declaration inside
|
|
132
|
-
const decl = node.childForFieldName("declaration");
|
|
133
|
-
if (decl) {
|
|
134
|
-
const inner = extractFromNode(decl);
|
|
135
|
-
if (inner) {
|
|
136
|
-
return inner.map((d) => ({ ...d, type: "export" }));
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
const name = node.text.slice(0, 60);
|
|
140
|
-
return [{ name, type: "export", text: node.text, startLine: node.startPosition.row + 1 }];
|
|
141
|
-
}
|
|
142
|
-
if (type === "variable_declaration" || type === "lexical_declaration") {
|
|
143
|
-
const results = [];
|
|
144
|
-
for (let i = 0; i < node.childCount; i++) {
|
|
145
|
-
const child = node.child(i);
|
|
146
|
-
if (child.type === "variable_declarator") {
|
|
147
|
-
const name = child.childForFieldName("name")?.text || "<unknown>";
|
|
148
|
-
// Check if value is an arrow function or function expression
|
|
149
|
-
const value = child.childForFieldName("value");
|
|
150
|
-
const isFn = value && (value.type === "arrow_function" || value.type === "function");
|
|
151
|
-
results.push({
|
|
152
|
-
name,
|
|
153
|
-
type: isFn ? "function" : "variable",
|
|
154
|
-
text: node.text,
|
|
155
|
-
startLine: node.startPosition.row + 1,
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
if (results.length)
|
|
160
|
-
return results;
|
|
161
|
-
}
|
|
162
|
-
// Expression statements like module.exports = ...
|
|
163
|
-
if (type === "expression_statement") {
|
|
164
|
-
const expr = node.child(0);
|
|
165
|
-
if (expr?.type === "assignment_expression") {
|
|
166
|
-
const left = expr.childForFieldName("left");
|
|
167
|
-
if (left?.text?.startsWith("module.exports")) {
|
|
168
|
-
return [{ name: "module.exports", type: "export", text: node.text, startLine: node.startPosition.row + 1 }];
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return null;
|
|
106
|
+
return (0, generic_extractor_1.extractDeclarationsGeneric)(source, ext);
|
|
173
107
|
}
|
|
174
108
|
//# sourceMappingURL=ast-diff.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-diff.js","sourceRoot":"","sources":["../../src/explain/ast-diff.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"ast-diff.js","sourceRoot":"","sources":["../../src/explain/ast-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ChangeType } from "./types";
|
|
2
|
+
export interface Declaration {
|
|
3
|
+
name: string;
|
|
4
|
+
type: ChangeType;
|
|
5
|
+
text: string;
|
|
6
|
+
startLine: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Extract declarations from source code using the config-driven system.
|
|
10
|
+
* Falls back to extracting named top-level nodes as "other" when no config exists
|
|
11
|
+
* but the language is parseable.
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractDeclarationsGeneric(source: string, ext: string): Declaration[];
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractDeclarationsGeneric = extractDeclarationsGeneric;
|
|
4
|
+
const language_configs_1 = require("./language-configs");
|
|
5
|
+
const parser_1 = require("../parsing/parser");
|
|
6
|
+
/**
|
|
7
|
+
* Extract declarations from source code using the config-driven system.
|
|
8
|
+
* Falls back to extracting named top-level nodes as "other" when no config exists
|
|
9
|
+
* but the language is parseable.
|
|
10
|
+
*/
|
|
11
|
+
function extractDeclarationsGeneric(source, ext) {
|
|
12
|
+
if (!source.trim())
|
|
13
|
+
return [];
|
|
14
|
+
const config = (0, language_configs_1.getConfigForExtension)(ext);
|
|
15
|
+
// Try to parse — if we can't, return empty
|
|
16
|
+
let tree;
|
|
17
|
+
try {
|
|
18
|
+
const result = (0, parser_1.parseSource)(source, ext);
|
|
19
|
+
tree = result.tree;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const root = tree.rootNode;
|
|
25
|
+
const decls = [];
|
|
26
|
+
for (let i = 0; i < root.childCount; i++) {
|
|
27
|
+
const node = root.child(i);
|
|
28
|
+
const extracted = config
|
|
29
|
+
? extractWithConfig(node, config)
|
|
30
|
+
: extractFallback(node);
|
|
31
|
+
if (extracted) {
|
|
32
|
+
decls.push(...extracted);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return decls;
|
|
36
|
+
}
|
|
37
|
+
function extractWithConfig(node, config) {
|
|
38
|
+
// Check for wrapper types (e.g. Python decorated_definition)
|
|
39
|
+
let targetNode = node;
|
|
40
|
+
if (config.wrapperTypes && node.type in config.wrapperTypes) {
|
|
41
|
+
const fieldName = config.wrapperTypes[node.type];
|
|
42
|
+
const inner = node.childForFieldName(fieldName);
|
|
43
|
+
if (inner) {
|
|
44
|
+
targetNode = inner;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const nodeConfig = config.nodeTypeMap[targetNode.type];
|
|
48
|
+
if (!nodeConfig)
|
|
49
|
+
return null;
|
|
50
|
+
if (nodeConfig.extractor) {
|
|
51
|
+
const results = nodeConfig.extractor(targetNode);
|
|
52
|
+
if (!results)
|
|
53
|
+
return null;
|
|
54
|
+
return results.map((r) => ({
|
|
55
|
+
name: r.name,
|
|
56
|
+
type: r.changeType || nodeConfig.changeType,
|
|
57
|
+
text: node.text,
|
|
58
|
+
startLine: node.startPosition.row + 1,
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
// Default: extract name via childForFieldName("name")
|
|
62
|
+
const name = targetNode.childForFieldName("name")?.text || "<anonymous>";
|
|
63
|
+
return [{
|
|
64
|
+
name,
|
|
65
|
+
type: nodeConfig.changeType,
|
|
66
|
+
text: node.text,
|
|
67
|
+
startLine: node.startPosition.row + 1,
|
|
68
|
+
}];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Fallback for languages without a config.
|
|
72
|
+
* Extracts any top-level node that has a "name" field.
|
|
73
|
+
*/
|
|
74
|
+
function extractFallback(node) {
|
|
75
|
+
const name = node.childForFieldName("name")?.text;
|
|
76
|
+
if (!name)
|
|
77
|
+
return null;
|
|
78
|
+
return [{
|
|
79
|
+
name,
|
|
80
|
+
type: "other",
|
|
81
|
+
text: node.text,
|
|
82
|
+
startLine: node.startPosition.row + 1,
|
|
83
|
+
}];
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=generic-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generic-extractor.js","sourceRoot":"","sources":["../../src/explain/generic-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,8 +8,15 @@ function escapeHtml(str) {
|
|
|
8
8
|
.replace(/>/g, ">")
|
|
9
9
|
.replace(/"/g, """);
|
|
10
10
|
}
|
|
11
|
+
const MAX_DIFF_LINES = 80;
|
|
11
12
|
function renderReport(report) {
|
|
12
13
|
const { explanation, summary, files } = report;
|
|
14
|
+
// --- Structural summary ---
|
|
15
|
+
const structuralSummaryHtml = buildStructuralSummary(files);
|
|
16
|
+
// --- Impact section ---
|
|
17
|
+
const impactHtml = explanation.impact.length > 0
|
|
18
|
+
? `<div class="impact-section">${explanation.impact.map((item) => `<span>${escapeHtml(item)}</span>`).join("")}</div>`
|
|
19
|
+
: "";
|
|
13
20
|
// --- Fixes section ---
|
|
14
21
|
const fixesHtml = explanation.fixes.length > 0
|
|
15
22
|
? explanation.fixes.map((f) => `<div class="fix-item"><span class="fix-icon">✓</span> ${escapeHtml(f.description)}</div>`).join("\n")
|
|
@@ -21,6 +28,8 @@ function renderReport(report) {
|
|
|
21
28
|
return `<div class="risk-item ${cls}"><span class="risk-label">${r.level}</span> ${escapeHtml(r.description)}</div>`;
|
|
22
29
|
}).join("\n")
|
|
23
30
|
: "";
|
|
31
|
+
// --- Common changes ---
|
|
32
|
+
const commonChangesHtml = buildCommonChanges(files);
|
|
24
33
|
// --- Per-file detail cards ---
|
|
25
34
|
// Build a map for both summary and notes
|
|
26
35
|
const fileExplanationData = new Map(explanation.fileExplanations.map((fe) => [fe.path, fe]));
|
|
@@ -35,9 +44,7 @@ function renderReport(report) {
|
|
|
35
44
|
const notesHtml = feData?.notes && feData.notes.length > 0
|
|
36
45
|
? `<div class="file-notes"><div class="file-notes-label">Things to note</div><ul>${feData.notes.map((n) => `<li>${escapeHtml(n)}</li>`).join("")}</ul></div>`
|
|
37
46
|
: "";
|
|
38
|
-
const diffHtml = f.rawDiff
|
|
39
|
-
? `<details class="diff-toggle"><summary>View diff</summary><pre class="diff-block">${colorDiff(f.rawDiff)}</pre></details>`
|
|
40
|
-
: "";
|
|
47
|
+
const diffHtml = f.rawDiff ? renderDiff(f.rawDiff) : "";
|
|
41
48
|
return `<div class="file-card">
|
|
42
49
|
<div class="file-header">
|
|
43
50
|
<span class="file-status status-${f.status}">${f.status}</span>
|
|
@@ -88,7 +95,7 @@ function renderReport(report) {
|
|
|
88
95
|
|
|
89
96
|
/* Stats */
|
|
90
97
|
.stats {
|
|
91
|
-
display: flex; gap: 20px; margin-bottom:
|
|
98
|
+
display: flex; gap: 20px; margin-bottom: 16px;
|
|
92
99
|
}
|
|
93
100
|
.stat {
|
|
94
101
|
font-size: 13px; color: #777; font-weight: 500;
|
|
@@ -97,6 +104,24 @@ function renderReport(report) {
|
|
|
97
104
|
.stat.additions b { color: #16a34a; }
|
|
98
105
|
.stat.deletions b { color: #dc2626; }
|
|
99
106
|
|
|
107
|
+
/* Structural summary */
|
|
108
|
+
.structural-summary {
|
|
109
|
+
font-size: 14px; color: #555; margin-bottom: 8px;
|
|
110
|
+
padding: 10px 14px; background: #f8fafc; border-radius: 6px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Impact */
|
|
114
|
+
.impact-section {
|
|
115
|
+
font-size: 14px; color: #555; margin-bottom: 28px;
|
|
116
|
+
padding: 10px 14px; background: #f8fafc; border-radius: 6px;
|
|
117
|
+
}
|
|
118
|
+
.impact-section span {
|
|
119
|
+
display: inline-block; margin-right: 12px;
|
|
120
|
+
}
|
|
121
|
+
.impact-section span::before {
|
|
122
|
+
content: "\\2022"; margin-right: 5px; color: #94a3b8;
|
|
123
|
+
}
|
|
124
|
+
|
|
100
125
|
/* Description — article lede */
|
|
101
126
|
.description {
|
|
102
127
|
font-size: 18px; line-height: 1.85; margin-bottom: 36px;
|
|
@@ -134,6 +159,22 @@ function renderReport(report) {
|
|
|
134
159
|
.risk-high { background: #fef2f2; border-left: 3px solid #ef4444; color: #991b1b; }
|
|
135
160
|
.risk-high .risk-label { background: #ef4444; }
|
|
136
161
|
|
|
162
|
+
/* AST-only notice */
|
|
163
|
+
.ast-only-notice {
|
|
164
|
+
padding: 12px 16px; margin-bottom: 32px;
|
|
165
|
+
background: #f8fafc; border: 1px dashed #cbd5e1; border-radius: 6px;
|
|
166
|
+
font-size: 14px; color: #64748b;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Common changes */
|
|
170
|
+
.common-changes { margin-bottom: 24px; }
|
|
171
|
+
.common-change-item {
|
|
172
|
+
padding: 6px 14px; font-size: 13px; color: #555;
|
|
173
|
+
border-left: 2px solid #cbd5e1; margin-bottom: 4px;
|
|
174
|
+
}
|
|
175
|
+
.common-change-item code { font-size: 12px; }
|
|
176
|
+
.common-change-files { font-size: 12px; color: #888; margin-left: 4px; }
|
|
177
|
+
|
|
137
178
|
/* File cards */
|
|
138
179
|
.file-card {
|
|
139
180
|
border: 1px solid #e5e7eb; border-radius: 8px;
|
|
@@ -156,7 +197,7 @@ function renderReport(report) {
|
|
|
156
197
|
|
|
157
198
|
.file-summary {
|
|
158
199
|
padding: 12px 14px; font-size: 14px; color: #444;
|
|
159
|
-
border-bottom: 1px solid #f5f5f5;
|
|
200
|
+
border-bottom: 1px solid #f5f5f5; font-weight: bold
|
|
160
201
|
}
|
|
161
202
|
.file-notes {
|
|
162
203
|
padding: 10px 14px; background: #fafbff;
|
|
@@ -199,6 +240,11 @@ function renderReport(report) {
|
|
|
199
240
|
font-family: "SF Mono", Menlo, monospace;
|
|
200
241
|
margin: 0; border-radius: 0;
|
|
201
242
|
}
|
|
243
|
+
.diff-truncation {
|
|
244
|
+
padding: 6px 14px; font-size: 12px; color: #888;
|
|
245
|
+
border-top: 1px solid #333; background: #252525;
|
|
246
|
+
}
|
|
247
|
+
.diff-show-full { cursor: pointer; color: #60a5fa; text-decoration: underline; background: none; border: none; font-size: 12px; }
|
|
202
248
|
|
|
203
249
|
/* Footer */
|
|
204
250
|
.footer {
|
|
@@ -223,21 +269,95 @@ function renderReport(report) {
|
|
|
223
269
|
<div class="stat deletions"><b>-${summary.deletions}</b> removed</div>
|
|
224
270
|
</div>
|
|
225
271
|
|
|
226
|
-
|
|
272
|
+
${structuralSummaryHtml}
|
|
273
|
+
|
|
274
|
+
${impactHtml}
|
|
275
|
+
|
|
276
|
+
${explanation.description
|
|
277
|
+
? `<div class="description">${escapeHtml(explanation.description)}</div>`
|
|
278
|
+
: `<div class="ast-only-notice">Structural analysis only — set ANTHROPIC_API_KEY for AI-powered explanations.</div>`}
|
|
227
279
|
|
|
228
280
|
${fixesHtml ? `<h2>What was fixed</h2>\n${fixesHtml}` : ""}
|
|
229
281
|
|
|
230
282
|
${risksHtml ? `<h2>Things to watch</h2>\n${risksHtml}` : ""}
|
|
231
283
|
|
|
284
|
+
${commonChangesHtml}
|
|
285
|
+
|
|
232
286
|
<h2>Changed files</h2>
|
|
233
287
|
${fileCards}
|
|
234
288
|
|
|
235
289
|
<div class="footer">
|
|
236
|
-
Generated by diffintel · ${explanation.tokenUsage.input + explanation.tokenUsage.output} tokens used
|
|
290
|
+
Generated by diffintel${explanation.tokenUsage.input + explanation.tokenUsage.output > 0 ? ` · ${explanation.tokenUsage.input + explanation.tokenUsage.output} tokens used` : ""}
|
|
237
291
|
</div>
|
|
238
292
|
</body>
|
|
239
293
|
</html>`;
|
|
240
294
|
}
|
|
295
|
+
function renderDiff(rawDiff) {
|
|
296
|
+
const lines = rawDiff.split("\n");
|
|
297
|
+
const totalLines = lines.length;
|
|
298
|
+
if (totalLines <= MAX_DIFF_LINES) {
|
|
299
|
+
return `<details class="diff-toggle"><summary>View diff</summary><pre class="diff-block">${colorDiff(rawDiff)}</pre></details>`;
|
|
300
|
+
}
|
|
301
|
+
const truncated = lines.slice(0, MAX_DIFF_LINES).join("\n");
|
|
302
|
+
const id = `diff-${Math.random().toString(36).slice(2, 8)}`;
|
|
303
|
+
return `<details class="diff-toggle"><summary>View diff</summary><pre class="diff-block" id="${id}-short">${colorDiff(truncated)}</pre><div class="diff-truncation" id="${id}-notice">Showing ${MAX_DIFF_LINES} of ${totalLines} lines <button class="diff-show-full" onclick="document.getElementById('${id}-short').style.display='none';document.getElementById('${id}-full').style.display='block';this.parentElement.style.display='none';">Show all</button></div><pre class="diff-block" id="${id}-full" style="display:none">${colorDiff(rawDiff)}</pre></details>`;
|
|
304
|
+
}
|
|
305
|
+
function buildStructuralSummary(files) {
|
|
306
|
+
const counts = new Map();
|
|
307
|
+
for (const f of files) {
|
|
308
|
+
for (const c of f.structuralChanges) {
|
|
309
|
+
const key = `${c.action}:${c.type}`;
|
|
310
|
+
counts.set(key, (counts.get(key) || 0) + 1);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (counts.size === 0)
|
|
314
|
+
return "";
|
|
315
|
+
const actionOrder = ["added", "modified", "removed"];
|
|
316
|
+
const parts = [];
|
|
317
|
+
for (const action of actionOrder) {
|
|
318
|
+
const items = [];
|
|
319
|
+
for (const [key, count] of counts) {
|
|
320
|
+
if (key.startsWith(action + ":")) {
|
|
321
|
+
const type = key.split(":")[1];
|
|
322
|
+
items.push(`${count} ${type}${count !== 1 ? "s" : ""}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (items.length > 0) {
|
|
326
|
+
parts.push(`${items.join(", ")} ${action}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (parts.length === 0)
|
|
330
|
+
return "";
|
|
331
|
+
const filesWithChanges = files.filter((f) => f.structuralChanges.length > 0).length;
|
|
332
|
+
return `<div class="structural-summary">${parts.join(" · ")} across ${filesWithChanges} file${filesWithChanges !== 1 ? "s" : ""}</div>`;
|
|
333
|
+
}
|
|
334
|
+
function buildCommonChanges(files) {
|
|
335
|
+
// Group changes by signature
|
|
336
|
+
const groups = new Map();
|
|
337
|
+
for (const f of files) {
|
|
338
|
+
for (const c of f.structuralChanges) {
|
|
339
|
+
const sig = `${c.action}:${c.type}:${c.name}`;
|
|
340
|
+
const group = groups.get(sig);
|
|
341
|
+
if (group) {
|
|
342
|
+
group.filePaths.push(f.path);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
groups.set(sig, { change: c, filePaths: [f.path] });
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// Filter to changes appearing in 2+ files
|
|
350
|
+
const common = [...groups.values()].filter((g) => g.filePaths.length >= 2);
|
|
351
|
+
if (common.length === 0)
|
|
352
|
+
return "";
|
|
353
|
+
const items = common.map((g) => {
|
|
354
|
+
const { change, filePaths } = g;
|
|
355
|
+
const actionSymbol = change.action === "added" ? "+" : change.action === "removed" ? "-" : "~";
|
|
356
|
+
const fileList = filePaths.map((p) => `<code>${escapeHtml(p)}</code>`).join(", ");
|
|
357
|
+
return `<div class="common-change-item">${actionSymbol} <code>${escapeHtml(change.name)}</code> (${change.type})<span class="common-change-files"> in ${fileList}</span></div>`;
|
|
358
|
+
}).join("\n");
|
|
359
|
+
return `<h2>Common changes</h2>\n${items}`;
|
|
360
|
+
}
|
|
241
361
|
function colorDiff(diff) {
|
|
242
362
|
return escapeHtml(diff)
|
|
243
363
|
.split("\n")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-report.js","sourceRoot":"","sources":["../../src/explain/html-report.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"html-report.js","sourceRoot":"","sources":["../../src/explain/html-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SyntaxNode } from "../parsing/parser";
|
|
2
|
+
import { ChangeType } from "./types";
|
|
3
|
+
export interface ExtractedDecl {
|
|
4
|
+
name: string;
|
|
5
|
+
changeType?: ChangeType;
|
|
6
|
+
}
|
|
7
|
+
export interface NodeTypeConfig {
|
|
8
|
+
changeType: ChangeType;
|
|
9
|
+
/**
|
|
10
|
+
* Custom extractor for nodes needing special name/type logic.
|
|
11
|
+
* Return null to skip the node entirely.
|
|
12
|
+
* Return array for nodes containing multiple declarations.
|
|
13
|
+
* If omitted, default: [{ name: node.childForFieldName("name")?.text }]
|
|
14
|
+
*/
|
|
15
|
+
extractor?: (node: SyntaxNode) => ExtractedDecl[] | null;
|
|
16
|
+
}
|
|
17
|
+
export interface LanguageConfig {
|
|
18
|
+
id: string;
|
|
19
|
+
extensions: string[];
|
|
20
|
+
treeSitterPackage: string;
|
|
21
|
+
/** Sub-property to access on the module (e.g. "php" for tree-sitter-php which exports { php, php_only }) */
|
|
22
|
+
treeSitterSubProperty?: string;
|
|
23
|
+
nodeTypeMap: Record<string, NodeTypeConfig>;
|
|
24
|
+
/** Wrapper nodes that contain the real declaration (e.g. Python decorated_definition) */
|
|
25
|
+
wrapperTypes?: Record<string, string>;
|
|
26
|
+
}
|
|
27
|
+
export declare const languageConfigs: LanguageConfig[];
|
|
28
|
+
/** Look up a language config by file extension */
|
|
29
|
+
export declare function getConfigForExtension(ext: string): LanguageConfig | null;
|
|
30
|
+
/** Get all supported file extensions across all configs */
|
|
31
|
+
export declare function getAllSupportedExtensions(): Set<string>;
|