@aiready/core 0.23.7 → 0.23.8
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/chunk-5SHLHMH7.mjs +760 -0
- package/dist/chunk-TJXR2CHZ.mjs +799 -0
- package/dist/client-CLulBnie.d.mts +1182 -0
- package/dist/client-CLulBnie.d.ts +1182 -0
- package/dist/client-CQwvp8ep.d.mts +1182 -0
- package/dist/client-CQwvp8ep.d.ts +1182 -0
- package/dist/client-PFPdeo-z.d.mts +1186 -0
- package/dist/client-PFPdeo-z.d.ts +1186 -0
- package/dist/client-wk2fgk1q.d.mts +1184 -0
- package/dist/client-wk2fgk1q.d.ts +1184 -0
- package/dist/client.d.mts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +42 -4
- package/dist/client.mjs +1 -1
- package/dist/index.d.mts +44 -20
- package/dist/index.d.ts +44 -20
- package/dist/index.js +374 -355
- package/dist/index.mjs +314 -337
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AIReadyConfigSchema,
|
|
2
3
|
AnalysisResultSchema,
|
|
3
4
|
AnalysisStatus,
|
|
4
5
|
AnalysisStatusSchema,
|
|
@@ -49,53 +50,102 @@ import {
|
|
|
49
50
|
getToolWeight,
|
|
50
51
|
normalizeToolName,
|
|
51
52
|
parseWeightString
|
|
52
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-TJXR2CHZ.mjs";
|
|
54
|
+
|
|
55
|
+
// src/utils/normalization.ts
|
|
56
|
+
function normalizeIssue(raw) {
|
|
57
|
+
return {
|
|
58
|
+
type: raw.type ?? "pattern-inconsistency" /* PatternInconsistency */,
|
|
59
|
+
severity: raw.severity ?? raw.severityLevel ?? "info" /* Info */,
|
|
60
|
+
message: raw.message ?? "Unknown issue",
|
|
61
|
+
location: raw.location ?? {
|
|
62
|
+
file: raw.fileName ?? raw.file ?? raw.filePath ?? "unknown",
|
|
63
|
+
line: raw.line ?? 1,
|
|
64
|
+
column: raw.column
|
|
65
|
+
},
|
|
66
|
+
suggestion: raw.suggestion
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function normalizeMetrics(raw) {
|
|
70
|
+
return {
|
|
71
|
+
tokenCost: raw.tokenCost ?? 0,
|
|
72
|
+
complexityScore: raw.complexityScore ?? 0,
|
|
73
|
+
consistencyScore: raw.consistencyScore,
|
|
74
|
+
docFreshnessScore: raw.docFreshnessScore,
|
|
75
|
+
aiSignalClarityScore: raw.aiSignalClarityScore,
|
|
76
|
+
agentGroundingScore: raw.agentGroundingScore,
|
|
77
|
+
testabilityScore: raw.testabilityScore,
|
|
78
|
+
docDriftScore: raw.docDriftScore,
|
|
79
|
+
dependencyHealthScore: raw.dependencyHealthScore,
|
|
80
|
+
modelContextTier: raw.modelContextTier,
|
|
81
|
+
estimatedMonthlyCost: raw.estimatedMonthlyCost,
|
|
82
|
+
estimatedDeveloperHours: raw.estimatedDeveloperHours,
|
|
83
|
+
comprehensionDifficultyIndex: raw.comprehensionDifficultyIndex,
|
|
84
|
+
totalSymbols: raw.totalSymbols,
|
|
85
|
+
totalExports: raw.totalExports
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function normalizeAnalysisResult(raw) {
|
|
89
|
+
const fileName = raw.fileName ?? raw.file ?? raw.filePath ?? "unknown";
|
|
90
|
+
const rawIssues = Array.isArray(raw.issues) ? raw.issues : [];
|
|
91
|
+
return {
|
|
92
|
+
fileName,
|
|
93
|
+
issues: rawIssues.map((issue) => {
|
|
94
|
+
if (typeof issue === "string") {
|
|
95
|
+
return {
|
|
96
|
+
type: "pattern-inconsistency" /* PatternInconsistency */,
|
|
97
|
+
// Default fallback
|
|
98
|
+
severity: raw.severity ?? "info" /* Info */,
|
|
99
|
+
message: issue,
|
|
100
|
+
location: { file: fileName, line: 1 }
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return normalizeIssue({
|
|
104
|
+
...issue,
|
|
105
|
+
fileName: issue.fileName ?? fileName,
|
|
106
|
+
severity: issue.severity ?? raw.severity
|
|
107
|
+
});
|
|
108
|
+
}),
|
|
109
|
+
metrics: normalizeMetrics(raw.metrics ?? {})
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function normalizeSpokeOutput(raw, toolName) {
|
|
113
|
+
const rawResults = Array.isArray(raw.results) ? raw.results : [];
|
|
114
|
+
return {
|
|
115
|
+
results: rawResults.map(normalizeAnalysisResult),
|
|
116
|
+
summary: raw.summary ?? {
|
|
117
|
+
totalFiles: rawResults.length,
|
|
118
|
+
totalIssues: 0,
|
|
119
|
+
criticalIssues: 0,
|
|
120
|
+
majorIssues: 0
|
|
121
|
+
},
|
|
122
|
+
metadata: {
|
|
123
|
+
toolName: raw.metadata?.toolName ?? toolName,
|
|
124
|
+
version: raw.metadata?.version,
|
|
125
|
+
timestamp: raw.metadata?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
126
|
+
config: raw.metadata?.config
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
53
130
|
|
|
54
131
|
// src/types/contract.ts
|
|
55
132
|
function validateSpokeOutput(toolName, output) {
|
|
56
|
-
const errors = [];
|
|
57
133
|
if (!output) {
|
|
58
134
|
return { valid: false, errors: ["Output is null or undefined"] };
|
|
59
135
|
}
|
|
60
|
-
if (!Array.isArray(output.results)) {
|
|
61
|
-
errors.push(`${toolName}: 'results' must be an array`);
|
|
62
|
-
} else {
|
|
63
|
-
output.results.forEach((res, idx) => {
|
|
64
|
-
const fileName = res.fileName || res.file || res.filePath;
|
|
65
|
-
if (!fileName)
|
|
66
|
-
errors.push(
|
|
67
|
-
`${toolName}: results[${idx}] missing 'fileName', 'file' or 'filePath'`
|
|
68
|
-
);
|
|
69
|
-
const issues = res.issues;
|
|
70
|
-
if (!Array.isArray(issues)) {
|
|
71
|
-
errors.push(`${toolName}: results[${idx}] 'issues' must be an array`);
|
|
72
|
-
} else if (issues.length > 0) {
|
|
73
|
-
issues.forEach((issue, iidx) => {
|
|
74
|
-
if (typeof issue === "string") return;
|
|
75
|
-
if (!issue.type && !res.file)
|
|
76
|
-
errors.push(
|
|
77
|
-
`${toolName}: results[${idx}].issues[${iidx}] missing 'type'`
|
|
78
|
-
);
|
|
79
|
-
if (!issue.severity && !res.severity)
|
|
80
|
-
errors.push(
|
|
81
|
-
`${toolName}: results[${idx}].issues[${iidx}] missing 'severity'`
|
|
82
|
-
);
|
|
83
|
-
const severity = issue.severity || res.severity;
|
|
84
|
-
if (severity && !["critical", "major", "minor", "info"].includes(severity)) {
|
|
85
|
-
errors.push(
|
|
86
|
-
`${toolName}: results[${idx}].issues[${iidx}] has invalid severity: ${severity}`
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
136
|
if (!output.summary) {
|
|
94
|
-
errors
|
|
137
|
+
return { valid: false, errors: [`${toolName}: missing 'summary'`] };
|
|
138
|
+
}
|
|
139
|
+
const normalized = normalizeSpokeOutput(output, toolName);
|
|
140
|
+
const result = SpokeOutputSchema.safeParse(normalized);
|
|
141
|
+
if (result.success) {
|
|
142
|
+
return { valid: true, errors: [] };
|
|
95
143
|
}
|
|
96
144
|
return {
|
|
97
|
-
valid:
|
|
98
|
-
errors
|
|
145
|
+
valid: false,
|
|
146
|
+
errors: result.error.issues.map(
|
|
147
|
+
(e) => `${toolName}: ${e.path.join(".")}: ${e.message}`
|
|
148
|
+
)
|
|
99
149
|
};
|
|
100
150
|
}
|
|
101
151
|
function validateWithSchema(schema, data) {
|
|
@@ -725,148 +775,67 @@ var TypeScriptParser = class {
|
|
|
725
775
|
this.extensions = [".ts", ".tsx", ".js", ".jsx"];
|
|
726
776
|
}
|
|
727
777
|
async initialize() {
|
|
728
|
-
return Promise.resolve();
|
|
729
778
|
}
|
|
730
|
-
|
|
731
|
-
return
|
|
732
|
-
loc: true,
|
|
733
|
-
range: true,
|
|
734
|
-
jsx: filePath.match(/\.[jt]sx$/i) !== null,
|
|
735
|
-
filePath,
|
|
736
|
-
sourceType: "module",
|
|
737
|
-
ecmaVersion: "latest",
|
|
738
|
-
comment: true
|
|
739
|
-
});
|
|
779
|
+
canHandle(filePath) {
|
|
780
|
+
return this.extensions.some((ext) => filePath.endsWith(ext));
|
|
740
781
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
const precedingStartOffset = Math.max(0, start - 1e3);
|
|
757
|
-
const absoluteStartOffset = precedingStartOffset + (lastMatch.index || 0);
|
|
758
|
-
const absoluteEndOffset = precedingStartOffset + matchEndIndex;
|
|
759
|
-
const codeBeforeStart = code.slice(0, absoluteStartOffset);
|
|
760
|
-
const startLines = codeBeforeStart.split("\n");
|
|
761
|
-
const startLine = startLines.length;
|
|
762
|
-
const startColumn = startLines[startLines.length - 1].length;
|
|
763
|
-
const codeBeforeEnd = code.slice(0, absoluteEndOffset);
|
|
764
|
-
const endLines = codeBeforeEnd.split("\n");
|
|
765
|
-
const endLine = endLines.length;
|
|
766
|
-
const endColumn = endLines[endLines.length - 1].length;
|
|
767
|
-
metadata.documentation = {
|
|
768
|
-
content: lastMatch[1].replace(/^\s*\*+/gm, "").trim(),
|
|
769
|
-
type: "jsdoc",
|
|
770
|
-
loc: {
|
|
771
|
-
start: { line: startLine, column: startColumn },
|
|
772
|
-
end: { line: endLine, column: endColumn }
|
|
773
|
-
}
|
|
774
|
-
};
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
const walk = (n) => {
|
|
778
|
-
if (!n) return;
|
|
779
|
-
if (n.type === "AssignmentExpression") {
|
|
780
|
-
metadata.isPure = false;
|
|
781
|
-
metadata.hasSideEffects = true;
|
|
782
|
-
}
|
|
783
|
-
if (n.type === "UpdateExpression") {
|
|
784
|
-
metadata.isPure = false;
|
|
785
|
-
metadata.hasSideEffects = true;
|
|
786
|
-
}
|
|
787
|
-
if (n.type === "CallExpression" && n.callee.type === "MemberExpression" && n.callee.object.type === "Identifier") {
|
|
788
|
-
const objName = n.callee.object.name;
|
|
789
|
-
if (["console", "process", "fs", "window", "document"].includes(objName)) {
|
|
790
|
-
metadata.isPure = false;
|
|
791
|
-
metadata.hasSideEffects = true;
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
if (n.type === "ThrowStatement") {
|
|
795
|
-
metadata.isPure = false;
|
|
796
|
-
metadata.hasSideEffects = true;
|
|
797
|
-
}
|
|
798
|
-
for (const key of Object.keys(n)) {
|
|
799
|
-
if (key === "parent") continue;
|
|
800
|
-
const child = n[key];
|
|
801
|
-
if (child && typeof child === "object") {
|
|
802
|
-
if (Array.isArray(child)) {
|
|
803
|
-
child.forEach((c) => c?.type && walk(c));
|
|
804
|
-
} else if (child.type) {
|
|
805
|
-
walk(child);
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
};
|
|
810
|
-
let nodeToAnalyze = node;
|
|
811
|
-
if (node.type === "ExportNamedDeclaration" && node.declaration) {
|
|
812
|
-
nodeToAnalyze = node.declaration;
|
|
813
|
-
} else if (node.type === "ExportDefaultDeclaration" && node.declaration) {
|
|
814
|
-
if (node.declaration.type !== "TSInterfaceDeclaration" && node.declaration.type !== "TSTypeAliasDeclaration") {
|
|
815
|
-
nodeToAnalyze = node.declaration;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
if (nodeToAnalyze.type === "FunctionDeclaration" || nodeToAnalyze.type === "FunctionExpression" || nodeToAnalyze.type === "ArrowFunctionExpression") {
|
|
819
|
-
if (nodeToAnalyze.body) walk(nodeToAnalyze.body);
|
|
820
|
-
} else if (nodeToAnalyze.type === "ClassDeclaration" || nodeToAnalyze.type === "ClassExpression") {
|
|
821
|
-
walk(nodeToAnalyze.body);
|
|
782
|
+
async getAST(code, filePath) {
|
|
783
|
+
try {
|
|
784
|
+
return parse(code, {
|
|
785
|
+
filePath,
|
|
786
|
+
loc: true,
|
|
787
|
+
range: true,
|
|
788
|
+
tokens: true,
|
|
789
|
+
comment: true,
|
|
790
|
+
jsx: filePath.endsWith("x")
|
|
791
|
+
});
|
|
792
|
+
} catch (error) {
|
|
793
|
+
throw new ParseError(error.message, filePath, {
|
|
794
|
+
line: error.lineNumber || 1,
|
|
795
|
+
column: error.column || 0
|
|
796
|
+
});
|
|
822
797
|
}
|
|
823
|
-
return metadata;
|
|
824
798
|
}
|
|
825
799
|
parse(code, filePath) {
|
|
826
800
|
try {
|
|
827
|
-
const isJavaScript = filePath.match(/\.jsx?$/i);
|
|
828
801
|
const ast = parse(code, {
|
|
802
|
+
filePath,
|
|
829
803
|
loc: true,
|
|
830
804
|
range: true,
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
ecmaVersion: "latest",
|
|
835
|
-
comment: true
|
|
805
|
+
tokens: true,
|
|
806
|
+
comment: true,
|
|
807
|
+
jsx: filePath.endsWith("x")
|
|
836
808
|
});
|
|
837
809
|
const imports = this.extractImports(ast);
|
|
838
|
-
const exports = this.extractExports(ast,
|
|
810
|
+
const exports = this.extractExports(ast, code);
|
|
839
811
|
return {
|
|
840
812
|
exports,
|
|
841
813
|
imports,
|
|
842
|
-
language:
|
|
843
|
-
warnings: []
|
|
814
|
+
language: this.language
|
|
844
815
|
};
|
|
845
816
|
} catch (error) {
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
);
|
|
817
|
+
throw new ParseError(error.message, filePath, {
|
|
818
|
+
line: error.lineNumber || 1,
|
|
819
|
+
column: error.column || 0
|
|
820
|
+
});
|
|
851
821
|
}
|
|
852
822
|
}
|
|
853
823
|
getNamingConventions() {
|
|
854
824
|
return {
|
|
855
|
-
// camelCase for variables and functions
|
|
856
825
|
variablePattern: /^[a-z][a-zA-Z0-9]*$/,
|
|
857
826
|
functionPattern: /^[a-z][a-zA-Z0-9]*$/,
|
|
858
|
-
// PascalCase for classes, types and interfaces
|
|
859
827
|
classPattern: /^[A-Z][a-zA-Z0-9]*$/,
|
|
860
|
-
typePattern: /^[A-Z][a-zA-Z0-9]*$/,
|
|
861
|
-
interfacePattern: /^[A-Z][a-zA-Z0-9]*$/,
|
|
862
|
-
// UPPER_CASE for constants
|
|
863
828
|
constantPattern: /^[A-Z][A-Z0-9_]*$/,
|
|
864
|
-
|
|
865
|
-
|
|
829
|
+
typePattern: /^[A-Z][a-zA-Z0-9]*$/,
|
|
830
|
+
interfacePattern: /^I?[A-Z][a-zA-Z0-9]*$/
|
|
866
831
|
};
|
|
867
832
|
}
|
|
868
|
-
|
|
869
|
-
|
|
833
|
+
analyzeMetadata(node, code) {
|
|
834
|
+
if (!code) return {};
|
|
835
|
+
return {
|
|
836
|
+
isPure: this.isLikelyPure(node),
|
|
837
|
+
hasSideEffects: !this.isLikelyPure(node)
|
|
838
|
+
};
|
|
870
839
|
}
|
|
871
840
|
extractImports(ast) {
|
|
872
841
|
const imports = [];
|
|
@@ -904,168 +873,165 @@ var TypeScriptParser = class {
|
|
|
904
873
|
}
|
|
905
874
|
return imports;
|
|
906
875
|
}
|
|
907
|
-
extractExports(ast,
|
|
876
|
+
extractExports(ast, code) {
|
|
908
877
|
const exports = [];
|
|
909
|
-
const importedNames = new Set(
|
|
910
|
-
imports.flatMap(
|
|
911
|
-
(imp) => imp.specifiers.filter((s) => s !== "*" && s !== "default")
|
|
912
|
-
)
|
|
913
|
-
);
|
|
914
878
|
for (const node of ast.body) {
|
|
915
|
-
if (node.type === "ExportNamedDeclaration"
|
|
916
|
-
|
|
917
|
-
node.declaration
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
879
|
+
if (node.type === "ExportNamedDeclaration") {
|
|
880
|
+
if (node.declaration) {
|
|
881
|
+
const declaration = node.declaration;
|
|
882
|
+
if ((declaration.type === "FunctionDeclaration" || declaration.type === "TSDeclareFunction") && declaration.id) {
|
|
883
|
+
exports.push(
|
|
884
|
+
this.createExport(
|
|
885
|
+
declaration.id.name,
|
|
886
|
+
"function",
|
|
887
|
+
node,
|
|
888
|
+
// Pass the outer ExportNamedDeclaration
|
|
889
|
+
code
|
|
890
|
+
)
|
|
891
|
+
);
|
|
892
|
+
} else if (declaration.type === "ClassDeclaration" && declaration.id) {
|
|
893
|
+
exports.push(
|
|
894
|
+
this.createExport(
|
|
895
|
+
declaration.id.name,
|
|
896
|
+
"class",
|
|
897
|
+
node,
|
|
898
|
+
// Pass the outer ExportNamedDeclaration
|
|
899
|
+
code
|
|
900
|
+
)
|
|
901
|
+
);
|
|
902
|
+
} else if (declaration.type === "TSTypeAliasDeclaration") {
|
|
903
|
+
exports.push(
|
|
904
|
+
this.createExport(
|
|
905
|
+
declaration.id.name,
|
|
906
|
+
"type",
|
|
907
|
+
node,
|
|
908
|
+
// Pass the outer ExportNamedDeclaration
|
|
909
|
+
code
|
|
910
|
+
)
|
|
911
|
+
);
|
|
912
|
+
} else if (declaration.type === "TSInterfaceDeclaration") {
|
|
913
|
+
exports.push(
|
|
914
|
+
this.createExport(
|
|
915
|
+
declaration.id.name,
|
|
916
|
+
"interface",
|
|
917
|
+
node,
|
|
918
|
+
// Pass the outer ExportNamedDeclaration
|
|
919
|
+
code
|
|
920
|
+
)
|
|
921
|
+
);
|
|
922
|
+
} else if (declaration.type === "VariableDeclaration") {
|
|
923
|
+
for (const decl of declaration.declarations) {
|
|
924
|
+
if (decl.id.type === "Identifier") {
|
|
925
|
+
exports.push(
|
|
926
|
+
this.createExport(
|
|
927
|
+
decl.id.name,
|
|
928
|
+
"const",
|
|
929
|
+
node,
|
|
930
|
+
// Pass the outer ExportNamedDeclaration
|
|
931
|
+
code,
|
|
932
|
+
decl.init
|
|
933
|
+
)
|
|
934
|
+
);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
934
938
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
type,
|
|
938
|
-
loc: node.loc ? {
|
|
939
|
-
start: {
|
|
940
|
-
line: node.loc.start.line,
|
|
941
|
-
column: node.loc.start.column
|
|
942
|
-
},
|
|
943
|
-
end: { line: node.loc.end.line, column: node.loc.end.column }
|
|
944
|
-
} : void 0,
|
|
945
|
-
...metadata
|
|
946
|
-
});
|
|
939
|
+
} else if (node.type === "ExportDefaultDeclaration") {
|
|
940
|
+
exports.push(this.createExport("default", "default", node, code));
|
|
947
941
|
}
|
|
948
942
|
}
|
|
949
943
|
return exports;
|
|
950
944
|
}
|
|
951
|
-
|
|
952
|
-
const
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
945
|
+
createExport(name, type, node, code, initializer) {
|
|
946
|
+
const documentation = this.extractDocumentation(node, code);
|
|
947
|
+
let methodCount;
|
|
948
|
+
let propertyCount;
|
|
949
|
+
let parameters;
|
|
950
|
+
let isPrimitive = false;
|
|
951
|
+
if (initializer) {
|
|
952
|
+
if (initializer.type === "Literal" || initializer.type === "TemplateLiteral" && initializer.expressions.length === 0) {
|
|
953
|
+
isPrimitive = true;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
const structNode = node.type === "ExportNamedDeclaration" ? node.declaration : node.type === "ExportDefaultDeclaration" ? node.declaration : node;
|
|
957
|
+
if (structNode.type === "ClassDeclaration" || structNode.type === "TSInterfaceDeclaration") {
|
|
958
|
+
const body = structNode.type === "ClassDeclaration" ? structNode.body.body : structNode.body.body;
|
|
959
|
+
methodCount = body.filter(
|
|
960
|
+
(m) => m.type === "MethodDefinition" || m.type === "TSMethodSignature"
|
|
961
|
+
).length;
|
|
962
|
+
propertyCount = body.filter(
|
|
963
|
+
(m) => m.type === "PropertyDefinition" || m.type === "TSPropertySignature"
|
|
964
|
+
).length;
|
|
965
|
+
if (structNode.type === "ClassDeclaration") {
|
|
966
|
+
const constructor = body.find(
|
|
967
|
+
(m) => m.type === "MethodDefinition" && m.kind === "constructor"
|
|
968
|
+
);
|
|
969
|
+
if (constructor && constructor.value && constructor.value.params) {
|
|
970
|
+
parameters = constructor.value.params.map((p) => {
|
|
971
|
+
if (p.type === "Identifier") return p.name;
|
|
972
|
+
if (p.type === "TSParameterProperty" && p.parameter.type === "Identifier") {
|
|
973
|
+
return p.parameter.name;
|
|
974
|
+
}
|
|
975
|
+
return void 0;
|
|
976
|
+
}).filter(Boolean);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
if (!parameters && (structNode.type === "FunctionDeclaration" || structNode.type === "TSDeclareFunction" || structNode.type === "MethodDefinition")) {
|
|
981
|
+
const funcNode = structNode.type === "MethodDefinition" ? structNode.value : structNode;
|
|
982
|
+
if (funcNode && funcNode.params) {
|
|
983
|
+
parameters = funcNode.params.map((p) => {
|
|
959
984
|
if (p.type === "Identifier") return p.name;
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
);
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
column: declaration.loc.end.column
|
|
1005
|
-
}
|
|
1006
|
-
} : void 0,
|
|
1007
|
-
...metadata
|
|
1008
|
-
});
|
|
1009
|
-
} else if (declaration.type === "VariableDeclaration") {
|
|
1010
|
-
for (const declarator of declaration.declarations) {
|
|
1011
|
-
if (declarator.id.type === "Identifier") {
|
|
1012
|
-
exports.push({
|
|
1013
|
-
name: declarator.id.name,
|
|
1014
|
-
type: "const",
|
|
1015
|
-
loc: declarator.loc ? {
|
|
1016
|
-
start: {
|
|
1017
|
-
line: declarator.loc.start.line,
|
|
1018
|
-
column: declarator.loc.start.column
|
|
1019
|
-
},
|
|
1020
|
-
end: {
|
|
1021
|
-
line: declarator.loc.end.line,
|
|
1022
|
-
column: declarator.loc.end.column
|
|
1023
|
-
}
|
|
1024
|
-
} : void 0,
|
|
1025
|
-
...metadata
|
|
1026
|
-
});
|
|
985
|
+
return void 0;
|
|
986
|
+
}).filter(Boolean);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
return {
|
|
990
|
+
name,
|
|
991
|
+
type,
|
|
992
|
+
isPrimitive,
|
|
993
|
+
loc: node.loc ? {
|
|
994
|
+
start: { line: node.loc.start.line, column: node.loc.start.column },
|
|
995
|
+
end: { line: node.loc.end.line, column: node.loc.end.column }
|
|
996
|
+
} : void 0,
|
|
997
|
+
documentation,
|
|
998
|
+
methodCount,
|
|
999
|
+
propertyCount,
|
|
1000
|
+
parameters,
|
|
1001
|
+
isPure: this.isLikelyPure(node),
|
|
1002
|
+
hasSideEffects: !this.isLikelyPure(node)
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
extractDocumentation(node, code) {
|
|
1006
|
+
if (node.range) {
|
|
1007
|
+
const start = node.range[0];
|
|
1008
|
+
const precedingCode = code.substring(0, start);
|
|
1009
|
+
const jsdocMatch = precedingCode.match(/\/\*\*([\s\S]*?)\*\/\s*$/);
|
|
1010
|
+
if (jsdocMatch) {
|
|
1011
|
+
return {
|
|
1012
|
+
content: jsdocMatch[1].trim(),
|
|
1013
|
+
type: "jsdoc"
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
return void 0;
|
|
1018
|
+
}
|
|
1019
|
+
isLikelyPure(node) {
|
|
1020
|
+
const structNode = node.type === "ExportNamedDeclaration" ? node.declaration : node.type === "ExportDefaultDeclaration" ? node.declaration : node;
|
|
1021
|
+
if (structNode.type === "VariableDeclaration" && structNode.kind === "const")
|
|
1022
|
+
return true;
|
|
1023
|
+
if (structNode.type === "FunctionDeclaration" || structNode.type === "TSDeclareFunction" || structNode.type === "MethodDefinition" && structNode.value) {
|
|
1024
|
+
const body = structNode.type === "MethodDefinition" ? structNode.value.body : structNode.body;
|
|
1025
|
+
if (body && body.type === "BlockStatement") {
|
|
1026
|
+
const bodyContent = JSON.stringify(body);
|
|
1027
|
+
if (bodyContent.includes('"name":"console"') || bodyContent.includes('"name":"process"') || bodyContent.includes('"type":"AssignmentExpression"')) {
|
|
1028
|
+
return false;
|
|
1027
1029
|
}
|
|
1030
|
+
return true;
|
|
1028
1031
|
}
|
|
1029
|
-
|
|
1030
|
-
exports.push({
|
|
1031
|
-
name: declaration.id.name,
|
|
1032
|
-
type: "type",
|
|
1033
|
-
loc: declaration.loc ? {
|
|
1034
|
-
start: {
|
|
1035
|
-
line: declaration.loc.start.line,
|
|
1036
|
-
column: declaration.loc.start.column
|
|
1037
|
-
},
|
|
1038
|
-
end: {
|
|
1039
|
-
line: declaration.loc.end.line,
|
|
1040
|
-
column: declaration.loc.end.column
|
|
1041
|
-
}
|
|
1042
|
-
} : void 0,
|
|
1043
|
-
...metadata
|
|
1044
|
-
});
|
|
1045
|
-
} else if (declaration.type === "TSInterfaceDeclaration") {
|
|
1046
|
-
const body = declaration.body.body;
|
|
1047
|
-
const methods = body.filter((m) => m.type === "TSMethodSignature");
|
|
1048
|
-
const properties = body.filter((m) => m.type === "TSPropertySignature");
|
|
1049
|
-
exports.push({
|
|
1050
|
-
name: declaration.id.name,
|
|
1051
|
-
type: "interface",
|
|
1052
|
-
methodCount: methods.length,
|
|
1053
|
-
propertyCount: properties.length || body.length,
|
|
1054
|
-
// Fallback to body.length
|
|
1055
|
-
loc: declaration.loc ? {
|
|
1056
|
-
start: {
|
|
1057
|
-
line: declaration.loc.start.line,
|
|
1058
|
-
column: declaration.loc.start.column
|
|
1059
|
-
},
|
|
1060
|
-
end: {
|
|
1061
|
-
line: declaration.loc.end.line,
|
|
1062
|
-
column: declaration.loc.end.column
|
|
1063
|
-
}
|
|
1064
|
-
} : void 0,
|
|
1065
|
-
...metadata
|
|
1066
|
-
});
|
|
1032
|
+
return true;
|
|
1067
1033
|
}
|
|
1068
|
-
return
|
|
1034
|
+
return false;
|
|
1069
1035
|
}
|
|
1070
1036
|
};
|
|
1071
1037
|
|
|
@@ -1355,7 +1321,7 @@ var PythonParser = class extends BaseLanguageParser {
|
|
|
1355
1321
|
* Extract import information using AST walk.
|
|
1356
1322
|
*
|
|
1357
1323
|
* @param rootNode - Root node of the Python AST.
|
|
1358
|
-
* @returns Array of discovered
|
|
1324
|
+
* @returns Array of discovered FileImport objects.
|
|
1359
1325
|
*/
|
|
1360
1326
|
extractImportsAST(rootNode) {
|
|
1361
1327
|
const imports = [];
|
|
@@ -1912,7 +1878,7 @@ var JavaParser = class extends BaseLanguageParser {
|
|
|
1912
1878
|
* Extract import information using AST walk.
|
|
1913
1879
|
*
|
|
1914
1880
|
* @param rootNode - Root node of the Java AST.
|
|
1915
|
-
* @returns Array of discovered
|
|
1881
|
+
* @returns Array of discovered FileImport objects.
|
|
1916
1882
|
*/
|
|
1917
1883
|
extractImportsAST(rootNode) {
|
|
1918
1884
|
const imports = [];
|
|
@@ -2144,7 +2110,7 @@ var CSharpParser = class extends BaseLanguageParser {
|
|
|
2144
2110
|
* Extract import information (usings) using AST walk.
|
|
2145
2111
|
*
|
|
2146
2112
|
* @param rootNode - Root node of the C# AST.
|
|
2147
|
-
* @returns Array of discovered
|
|
2113
|
+
* @returns Array of discovered FileImport objects.
|
|
2148
2114
|
*/
|
|
2149
2115
|
extractImportsAST(rootNode) {
|
|
2150
2116
|
const imports = [];
|
|
@@ -2397,7 +2363,7 @@ var GoParser = class extends BaseLanguageParser {
|
|
|
2397
2363
|
* Extract import information using AST walk.
|
|
2398
2364
|
*
|
|
2399
2365
|
* @param rootNode - Root node of the Go AST.
|
|
2400
|
-
* @returns Array of discovered
|
|
2366
|
+
* @returns Array of discovered FileImport objects.
|
|
2401
2367
|
*/
|
|
2402
2368
|
extractImportsAST(rootNode) {
|
|
2403
2369
|
const imports = [];
|
|
@@ -2885,10 +2851,25 @@ async function loadConfig(rootDir) {
|
|
|
2885
2851
|
const content = readFileSync(configPath, "utf-8");
|
|
2886
2852
|
config = JSON.parse(content);
|
|
2887
2853
|
}
|
|
2888
|
-
|
|
2889
|
-
|
|
2854
|
+
const legacyKeys = ["toolConfigs"];
|
|
2855
|
+
const rootLevelTools = [
|
|
2856
|
+
"pattern-detect",
|
|
2857
|
+
"context-analyzer",
|
|
2858
|
+
"naming-consistency",
|
|
2859
|
+
"ai-signal-clarity"
|
|
2860
|
+
];
|
|
2861
|
+
const allKeys = Object.keys(config);
|
|
2862
|
+
const foundLegacy = allKeys.filter(
|
|
2863
|
+
(k) => legacyKeys.includes(k) || rootLevelTools.includes(k)
|
|
2864
|
+
);
|
|
2865
|
+
if (foundLegacy.length > 0) {
|
|
2866
|
+
console.warn(
|
|
2867
|
+
`\u26A0\uFE0F Legacy configuration keys found: ${foundLegacy.join(
|
|
2868
|
+
", "
|
|
2869
|
+
)}. These are deprecated and should be moved under the "tools" key.`
|
|
2870
|
+
);
|
|
2890
2871
|
}
|
|
2891
|
-
return config;
|
|
2872
|
+
return AIReadyConfigSchema.parse(config);
|
|
2892
2873
|
} catch (error) {
|
|
2893
2874
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2894
2875
|
const configError = new Error(
|
|
@@ -2916,12 +2897,10 @@ function mergeConfigWithDefaults(userConfig, defaults) {
|
|
|
2916
2897
|
if (userConfig.scan.include) mergedConfig.include = userConfig.scan.include;
|
|
2917
2898
|
if (userConfig.scan.exclude) mergedConfig.exclude = userConfig.scan.exclude;
|
|
2918
2899
|
}
|
|
2919
|
-
|
|
2920
|
-
if (toolOverrides) {
|
|
2900
|
+
if (userConfig.tools) {
|
|
2921
2901
|
if (!mergedConfig.toolConfigs) mergedConfig.toolConfigs = {};
|
|
2922
|
-
for (const [toolName, toolConfig] of Object.entries(
|
|
2902
|
+
for (const [toolName, toolConfig] of Object.entries(userConfig.tools)) {
|
|
2923
2903
|
if (typeof toolConfig === "object" && toolConfig !== null) {
|
|
2924
|
-
mergedConfig[toolName] = { ...mergedConfig[toolName], ...toolConfig };
|
|
2925
2904
|
mergedConfig.toolConfigs[toolName] = {
|
|
2926
2905
|
...mergedConfig.toolConfigs[toolName],
|
|
2927
2906
|
...toolConfig
|
|
@@ -2937,6 +2916,13 @@ function mergeConfigWithDefaults(userConfig, defaults) {
|
|
|
2937
2916
|
|
|
2938
2917
|
// src/business/pricing-models.ts
|
|
2939
2918
|
var MODEL_PRICING_PRESETS = {
|
|
2919
|
+
"gpt-5.4-mini": {
|
|
2920
|
+
name: "GPT-5.4 Mini",
|
|
2921
|
+
pricePer1KInputTokens: 1e-4,
|
|
2922
|
+
pricePer1KOutputTokens: 4e-4,
|
|
2923
|
+
contextTier: "extended",
|
|
2924
|
+
typicalQueriesPerDevPerDay: 200
|
|
2925
|
+
},
|
|
2940
2926
|
"gpt-5.3": {
|
|
2941
2927
|
name: "GPT-5.3",
|
|
2942
2928
|
pricePer1KInputTokens: 2e-3,
|
|
@@ -2958,20 +2944,6 @@ var MODEL_PRICING_PRESETS = {
|
|
|
2958
2944
|
contextTier: "frontier",
|
|
2959
2945
|
typicalQueriesPerDevPerDay: 120
|
|
2960
2946
|
},
|
|
2961
|
-
"gpt-4o": {
|
|
2962
|
-
name: "GPT-4o (legacy)",
|
|
2963
|
-
pricePer1KInputTokens: 5e-3,
|
|
2964
|
-
pricePer1KOutputTokens: 0.015,
|
|
2965
|
-
contextTier: "extended",
|
|
2966
|
-
typicalQueriesPerDevPerDay: 60
|
|
2967
|
-
},
|
|
2968
|
-
"claude-3-5-sonnet": {
|
|
2969
|
-
name: "Claude 3.5 Sonnet (legacy)",
|
|
2970
|
-
pricePer1KInputTokens: 3e-3,
|
|
2971
|
-
pricePer1KOutputTokens: 0.015,
|
|
2972
|
-
contextTier: "extended",
|
|
2973
|
-
typicalQueriesPerDevPerDay: 80
|
|
2974
|
-
},
|
|
2975
2947
|
"gemini-1-5-pro": {
|
|
2976
2948
|
name: "Gemini 1.5 Pro (legacy)",
|
|
2977
2949
|
pricePer1KInputTokens: 125e-5,
|
|
@@ -2995,7 +2967,7 @@ var MODEL_PRICING_PRESETS = {
|
|
|
2995
2967
|
}
|
|
2996
2968
|
};
|
|
2997
2969
|
function getModelPreset(modelId) {
|
|
2998
|
-
return MODEL_PRICING_PRESETS[modelId] ?? MODEL_PRICING_PRESETS["
|
|
2970
|
+
return MODEL_PRICING_PRESETS[modelId] ?? MODEL_PRICING_PRESETS["gpt-5.4-mini"];
|
|
2999
2971
|
}
|
|
3000
2972
|
|
|
3001
2973
|
// src/business/cost-metrics.ts
|
|
@@ -3016,7 +2988,7 @@ function calculateMonthlyCost(tokenWaste, config = {}) {
|
|
|
3016
2988
|
// Added baseline chattiness
|
|
3017
2989
|
}
|
|
3018
2990
|
});
|
|
3019
|
-
const preset = getModelPreset("
|
|
2991
|
+
const preset = getModelPreset("gpt-5.4-mini");
|
|
3020
2992
|
return estimateCostFromBudget(budget, preset, config);
|
|
3021
2993
|
}
|
|
3022
2994
|
function calculateTokenBudget(params) {
|
|
@@ -3862,12 +3834,12 @@ function calculateTestabilityIndex(params) {
|
|
|
3862
3834
|
const rawCoverageRatio = sourceFiles > 0 ? testFiles / sourceFiles : 0;
|
|
3863
3835
|
const testCoverageRatio = Math.min(100, Math.round(rawCoverageRatio * 100));
|
|
3864
3836
|
const purityScore = Math.round(
|
|
3865
|
-
(totalFunctions > 0 ? pureFunctions / totalFunctions : 0.
|
|
3837
|
+
(totalFunctions > 0 ? pureFunctions / totalFunctions : 0.7) * 100
|
|
3866
3838
|
);
|
|
3867
3839
|
const dependencyInjectionScore = Math.round(
|
|
3868
3840
|
Math.min(
|
|
3869
3841
|
100,
|
|
3870
|
-
(totalClasses > 0 ? injectionPatterns / totalClasses : 0.
|
|
3842
|
+
(totalClasses > 0 ? injectionPatterns / totalClasses : 0.8) * 100
|
|
3871
3843
|
)
|
|
3872
3844
|
);
|
|
3873
3845
|
const interfaceFocusScore = Math.max(
|
|
@@ -3948,9 +3920,9 @@ function calculateDocDrift(params) {
|
|
|
3948
3920
|
const outdatedRatio = totalExports > 0 ? outdatedComments / totalExports : 0;
|
|
3949
3921
|
const complexityRatio = totalExports > 0 ? undocumentedComplexity / totalExports : 0;
|
|
3950
3922
|
const driftRatio = totalExports > 0 ? actualDrift / totalExports : 0;
|
|
3951
|
-
const DRIFT_THRESHOLD = 0.
|
|
3952
|
-
const OUTDATED_THRESHOLD = 0.
|
|
3953
|
-
const COMPLEXITY_THRESHOLD = 0.
|
|
3923
|
+
const DRIFT_THRESHOLD = 0.35;
|
|
3924
|
+
const OUTDATED_THRESHOLD = 0.5;
|
|
3925
|
+
const COMPLEXITY_THRESHOLD = 0.3;
|
|
3954
3926
|
const UNCOMMENTED_THRESHOLD = 0.8;
|
|
3955
3927
|
const driftRisk = Math.min(100, driftRatio / DRIFT_THRESHOLD * 100);
|
|
3956
3928
|
const outdatedRisk = Math.min(
|
|
@@ -4415,6 +4387,7 @@ function emitIssuesAsAnnotations(issues) {
|
|
|
4415
4387
|
});
|
|
4416
4388
|
}
|
|
4417
4389
|
export {
|
|
4390
|
+
AIReadyConfigSchema,
|
|
4418
4391
|
AnalysisResultSchema,
|
|
4419
4392
|
AnalysisStatus,
|
|
4420
4393
|
AnalysisStatusSchema,
|
|
@@ -4540,6 +4513,10 @@ export {
|
|
|
4540
4513
|
loadMergedConfig,
|
|
4541
4514
|
loadScoreHistory,
|
|
4542
4515
|
mergeConfigWithDefaults,
|
|
4516
|
+
normalizeAnalysisResult,
|
|
4517
|
+
normalizeIssue,
|
|
4518
|
+
normalizeMetrics,
|
|
4519
|
+
normalizeSpokeOutput,
|
|
4543
4520
|
normalizeToolName,
|
|
4544
4521
|
parseFileExports,
|
|
4545
4522
|
parseWeightString,
|