@aiready/agent-grounding 0.13.18 → 0.13.20
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/.turbo/turbo-build.log +24 -23
- package/.turbo/turbo-lint.log +5 -4
- package/.turbo/turbo-test.log +19 -18
- package/dist/chunk-ER6KHJNN.mjs +251 -0
- package/dist/chunk-OFAWUHBZ.mjs +260 -0
- package/dist/chunk-SS3ETQAF.mjs +276 -0
- package/dist/cli.js +84 -153
- package/dist/cli.mjs +38 -61
- package/dist/index.d.mts +2 -6
- package/dist/index.d.ts +2 -6
- package/dist/index.js +49 -94
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
- package/src/__tests__/scoring.test.ts +1 -1
- package/src/analyzer.ts +45 -64
- package/src/cli.ts +37 -69
- package/src/scoring.ts +21 -55
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
// src/analyzer.ts
|
|
2
|
+
import {
|
|
3
|
+
scanEntries,
|
|
4
|
+
calculateAgentGrounding,
|
|
5
|
+
VAGUE_FILE_NAMES,
|
|
6
|
+
Severity,
|
|
7
|
+
IssueType,
|
|
8
|
+
emitProgress
|
|
9
|
+
} from "@aiready/core";
|
|
10
|
+
import { readFileSync, existsSync, statSync } from "fs";
|
|
11
|
+
import { join, extname, basename, relative } from "path";
|
|
12
|
+
import { parse } from "@typescript-eslint/typescript-estree";
|
|
13
|
+
function analyzeFile(filePath) {
|
|
14
|
+
let code;
|
|
15
|
+
try {
|
|
16
|
+
code = readFileSync(filePath, "utf-8");
|
|
17
|
+
} catch {
|
|
18
|
+
return {
|
|
19
|
+
isBarrel: false,
|
|
20
|
+
exportedNames: [],
|
|
21
|
+
untypedExports: 0,
|
|
22
|
+
totalExports: 0,
|
|
23
|
+
domainTerms: []
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
let ast;
|
|
27
|
+
try {
|
|
28
|
+
ast = parse(code, {
|
|
29
|
+
jsx: filePath.endsWith(".tsx") || filePath.endsWith(".jsx"),
|
|
30
|
+
range: false,
|
|
31
|
+
loc: false
|
|
32
|
+
});
|
|
33
|
+
} catch {
|
|
34
|
+
return {
|
|
35
|
+
isBarrel: false,
|
|
36
|
+
exportedNames: [],
|
|
37
|
+
untypedExports: 0,
|
|
38
|
+
totalExports: 0,
|
|
39
|
+
domainTerms: []
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
let isBarrel = false;
|
|
43
|
+
const exportedNames = [];
|
|
44
|
+
let untypedExports = 0;
|
|
45
|
+
let totalExports = 0;
|
|
46
|
+
const domainTerms = [];
|
|
47
|
+
for (const node of ast.body) {
|
|
48
|
+
if (node.type === "ExportAllDeclaration") {
|
|
49
|
+
isBarrel = true;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (node.type === "ExportNamedDeclaration") {
|
|
53
|
+
totalExports++;
|
|
54
|
+
const decl = node.declaration;
|
|
55
|
+
if (decl) {
|
|
56
|
+
const name = decl.id?.name ?? decl.declarations?.[0]?.id?.name;
|
|
57
|
+
if (name) {
|
|
58
|
+
exportedNames.push(name);
|
|
59
|
+
domainTerms.push(
|
|
60
|
+
...name.replace(/([A-Z])/g, " $1").toLowerCase().split(/\s+/).filter(Boolean)
|
|
61
|
+
);
|
|
62
|
+
const hasType = decl.returnType != null || decl.declarations?.[0]?.id?.typeAnnotation != null || decl.typeParameters != null;
|
|
63
|
+
if (!hasType) untypedExports++;
|
|
64
|
+
}
|
|
65
|
+
} else if (node.specifiers && node.specifiers.length > 0) {
|
|
66
|
+
isBarrel = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (node.type === "ExportDefaultDeclaration") {
|
|
70
|
+
totalExports++;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return { isBarrel, exportedNames, untypedExports, totalExports, domainTerms };
|
|
74
|
+
}
|
|
75
|
+
function detectInconsistentTerms(allTerms) {
|
|
76
|
+
const termFreq = /* @__PURE__ */ new Map();
|
|
77
|
+
for (const term of allTerms) {
|
|
78
|
+
if (term.length >= 3) {
|
|
79
|
+
termFreq.set(term, (termFreq.get(term) ?? 0) + 1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const orphans = [...termFreq.values()].filter((count) => count === 1).length;
|
|
83
|
+
const common = [...termFreq.values()].filter((count) => count >= 3).length;
|
|
84
|
+
const vocabularySize = termFreq.size;
|
|
85
|
+
const inconsistent = Math.max(0, orphans - common * 2);
|
|
86
|
+
return { inconsistent, vocabularySize };
|
|
87
|
+
}
|
|
88
|
+
async function analyzeAgentGrounding(options) {
|
|
89
|
+
const rootDir = options.rootDir;
|
|
90
|
+
const maxRecommendedDepth = options.maxRecommendedDepth ?? 4;
|
|
91
|
+
const readmeStaleDays = options.readmeStaleDays ?? 90;
|
|
92
|
+
const { files, dirs: rawDirs } = await scanEntries({
|
|
93
|
+
...options,
|
|
94
|
+
include: options.include || ["**/*.{ts,tsx,js,jsx}"]
|
|
95
|
+
});
|
|
96
|
+
const { files: allFiles } = await scanEntries({
|
|
97
|
+
...options,
|
|
98
|
+
include: ["**/*"]
|
|
99
|
+
});
|
|
100
|
+
const dirs = rawDirs.map((d) => ({
|
|
101
|
+
path: d,
|
|
102
|
+
depth: relative(rootDir, d).split(/[/\\]/).filter(Boolean).length
|
|
103
|
+
}));
|
|
104
|
+
const deepDirectories = dirs.filter(
|
|
105
|
+
(d) => d.depth > maxRecommendedDepth
|
|
106
|
+
).length;
|
|
107
|
+
const additionalVague = new Set(
|
|
108
|
+
(options.additionalVagueNames ?? []).map((n) => n.toLowerCase())
|
|
109
|
+
);
|
|
110
|
+
let vagueFileNames = 0;
|
|
111
|
+
for (const f of allFiles) {
|
|
112
|
+
const base = basename(f, extname(f)).toLowerCase();
|
|
113
|
+
if (VAGUE_FILE_NAMES.has(base) || additionalVague.has(base)) {
|
|
114
|
+
vagueFileNames++;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const readmePath = join(rootDir, "README.md");
|
|
118
|
+
const hasRootReadme = existsSync(readmePath);
|
|
119
|
+
let readmeIsFresh = false;
|
|
120
|
+
if (hasRootReadme) {
|
|
121
|
+
try {
|
|
122
|
+
const stat = statSync(readmePath);
|
|
123
|
+
const ageDays = (Date.now() - stat.mtimeMs) / (1e3 * 60 * 60 * 24);
|
|
124
|
+
readmeIsFresh = ageDays < readmeStaleDays;
|
|
125
|
+
} catch {
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const allDomainTerms = [];
|
|
129
|
+
let barrelExports = 0;
|
|
130
|
+
let untypedExports = 0;
|
|
131
|
+
let totalExports = 0;
|
|
132
|
+
let processed = 0;
|
|
133
|
+
for (const f of files) {
|
|
134
|
+
processed++;
|
|
135
|
+
emitProgress(
|
|
136
|
+
processed,
|
|
137
|
+
files.length,
|
|
138
|
+
"agent-grounding",
|
|
139
|
+
"analyzing files",
|
|
140
|
+
options.onProgress
|
|
141
|
+
);
|
|
142
|
+
const analysis = analyzeFile(f);
|
|
143
|
+
if (analysis.isBarrel) barrelExports++;
|
|
144
|
+
untypedExports += analysis.untypedExports;
|
|
145
|
+
totalExports += analysis.totalExports;
|
|
146
|
+
allDomainTerms.push(...analysis.domainTerms);
|
|
147
|
+
}
|
|
148
|
+
const {
|
|
149
|
+
inconsistent: inconsistentDomainTerms,
|
|
150
|
+
vocabularySize: domainVocabularySize
|
|
151
|
+
} = detectInconsistentTerms(allDomainTerms);
|
|
152
|
+
const groundingResult = calculateAgentGrounding({
|
|
153
|
+
deepDirectories,
|
|
154
|
+
totalDirectories: dirs.length,
|
|
155
|
+
vagueFileNames,
|
|
156
|
+
totalFiles: files.length,
|
|
157
|
+
hasRootReadme,
|
|
158
|
+
readmeIsFresh,
|
|
159
|
+
barrelExports,
|
|
160
|
+
untypedExports,
|
|
161
|
+
totalExports: Math.max(1, totalExports),
|
|
162
|
+
inconsistentDomainTerms,
|
|
163
|
+
domainVocabularySize: Math.max(1, domainVocabularySize)
|
|
164
|
+
});
|
|
165
|
+
const issues = [];
|
|
166
|
+
if (groundingResult.dimensions.structureClarityScore < 70) {
|
|
167
|
+
issues.push({
|
|
168
|
+
type: IssueType.AgentNavigationFailure,
|
|
169
|
+
dimension: "structure-clarity",
|
|
170
|
+
severity: Severity.Major,
|
|
171
|
+
message: `${deepDirectories} directories exceed recommended depth of ${maxRecommendedDepth} \u2014 agents struggle to navigate deep trees.`,
|
|
172
|
+
location: { file: rootDir, line: 0 },
|
|
173
|
+
suggestion: `Flatten nested directories to ${maxRecommendedDepth} levels or fewer.`
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
if (groundingResult.dimensions.selfDocumentationScore < 70) {
|
|
177
|
+
issues.push({
|
|
178
|
+
type: IssueType.AgentNavigationFailure,
|
|
179
|
+
dimension: "self-documentation",
|
|
180
|
+
severity: Severity.Major,
|
|
181
|
+
message: `${vagueFileNames} files use vague names (utils, helpers, misc) \u2014 an agent cannot determine their purpose from the name alone.`,
|
|
182
|
+
location: { file: rootDir, line: 0 },
|
|
183
|
+
suggestion: "Rename to domain-specific names: e.g., userAuthUtils \u2192 tokenValidator."
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
if (!hasRootReadme) {
|
|
187
|
+
issues.push({
|
|
188
|
+
type: IssueType.AgentNavigationFailure,
|
|
189
|
+
dimension: "entry-point",
|
|
190
|
+
severity: Severity.Critical,
|
|
191
|
+
message: "No root README.md found \u2014 agents have no orientation document to start from.",
|
|
192
|
+
location: { file: join(rootDir, "README.md"), line: 0 },
|
|
193
|
+
suggestion: "Add a README.md explaining the project structure, entry points, and key conventions."
|
|
194
|
+
});
|
|
195
|
+
} else if (!readmeIsFresh) {
|
|
196
|
+
issues.push({
|
|
197
|
+
type: IssueType.AgentNavigationFailure,
|
|
198
|
+
dimension: "entry-point",
|
|
199
|
+
severity: Severity.Minor,
|
|
200
|
+
message: `README.md is stale (>${readmeStaleDays} days without updates) \u2014 agents may be misled by outdated context.`,
|
|
201
|
+
location: { file: readmePath, line: 0 },
|
|
202
|
+
suggestion: "Update README.md to reflect the current codebase structure."
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
if (groundingResult.dimensions.apiClarityScore < 70) {
|
|
206
|
+
issues.push({
|
|
207
|
+
type: IssueType.AgentNavigationFailure,
|
|
208
|
+
dimension: "api-clarity",
|
|
209
|
+
severity: Severity.Major,
|
|
210
|
+
message: `${untypedExports} of ${totalExports} public exports lack TypeScript type annotations \u2014 agents cannot infer the API contract.`,
|
|
211
|
+
location: { file: rootDir, line: 0 },
|
|
212
|
+
suggestion: "Add explicit return type and parameter annotations to all exported functions."
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (groundingResult.dimensions.domainConsistencyScore < 70) {
|
|
216
|
+
issues.push({
|
|
217
|
+
type: IssueType.AgentNavigationFailure,
|
|
218
|
+
dimension: "domain-consistency",
|
|
219
|
+
severity: Severity.Major,
|
|
220
|
+
message: `${inconsistentDomainTerms} domain terms appear to be used inconsistently \u2014 agents get confused when one concept has multiple names.`,
|
|
221
|
+
location: { file: rootDir, line: 0 },
|
|
222
|
+
suggestion: "Establish a domain glossary and enforce one term per concept across the codebase."
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
summary: {
|
|
227
|
+
filesAnalyzed: files.length,
|
|
228
|
+
directoriesAnalyzed: dirs.length,
|
|
229
|
+
score: groundingResult.score,
|
|
230
|
+
rating: groundingResult.rating,
|
|
231
|
+
dimensions: groundingResult.dimensions
|
|
232
|
+
},
|
|
233
|
+
issues,
|
|
234
|
+
rawData: {
|
|
235
|
+
deepDirectories,
|
|
236
|
+
totalDirectories: dirs.length,
|
|
237
|
+
vagueFileNames,
|
|
238
|
+
totalFiles: files.length,
|
|
239
|
+
hasRootReadme,
|
|
240
|
+
readmeIsFresh,
|
|
241
|
+
barrelExports,
|
|
242
|
+
untypedExports,
|
|
243
|
+
totalExports,
|
|
244
|
+
inconsistentDomainTerms,
|
|
245
|
+
domainVocabularySize
|
|
246
|
+
},
|
|
247
|
+
recommendations: groundingResult.recommendations
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// src/scoring.ts
|
|
252
|
+
import { ToolName, buildStandardToolScore } from "@aiready/core";
|
|
253
|
+
function calculateGroundingScore(report) {
|
|
254
|
+
const { summary, rawData, recommendations } = report;
|
|
255
|
+
return buildStandardToolScore({
|
|
256
|
+
toolName: ToolName.AgentGrounding,
|
|
257
|
+
score: summary.score,
|
|
258
|
+
rawData,
|
|
259
|
+
dimensions: summary.dimensions,
|
|
260
|
+
dimensionNames: {
|
|
261
|
+
structureClarityScore: "Structure Clarity",
|
|
262
|
+
selfDocumentationScore: "Self-Documentation",
|
|
263
|
+
entryPointScore: "Entry Points",
|
|
264
|
+
apiClarityScore: "API Clarity",
|
|
265
|
+
domainConsistencyScore: "Domain Consistency"
|
|
266
|
+
},
|
|
267
|
+
recommendations,
|
|
268
|
+
recommendationImpact: 6,
|
|
269
|
+
rating: summary.rating
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export {
|
|
274
|
+
analyzeAgentGrounding,
|
|
275
|
+
calculateGroundingScore
|
|
276
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -30,68 +30,45 @@ var import_commander = require("commander");
|
|
|
30
30
|
var import_core = require("@aiready/core");
|
|
31
31
|
var import_fs = require("fs");
|
|
32
32
|
var import_path = require("path");
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
async function analyzeFile(filePath) {
|
|
34
|
+
const result = {
|
|
35
|
+
isBarrel: false,
|
|
36
|
+
exportedNames: [],
|
|
37
|
+
untypedExports: 0,
|
|
38
|
+
totalExports: 0,
|
|
39
|
+
domainTerms: []
|
|
40
|
+
};
|
|
41
|
+
const parser = await (0, import_core.getParser)(filePath);
|
|
42
|
+
if (!parser) return result;
|
|
35
43
|
let code;
|
|
36
44
|
try {
|
|
37
45
|
code = (0, import_fs.readFileSync)(filePath, "utf-8");
|
|
38
46
|
} catch {
|
|
39
|
-
return
|
|
40
|
-
isBarrel: false,
|
|
41
|
-
exportedNames: [],
|
|
42
|
-
untypedExports: 0,
|
|
43
|
-
totalExports: 0,
|
|
44
|
-
domainTerms: []
|
|
45
|
-
};
|
|
47
|
+
return result;
|
|
46
48
|
}
|
|
47
|
-
let ast;
|
|
48
49
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
untypedExports: 0,
|
|
59
|
-
totalExports: 0,
|
|
60
|
-
domainTerms: []
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
let isBarrel = false;
|
|
64
|
-
const exportedNames = [];
|
|
65
|
-
let untypedExports = 0;
|
|
66
|
-
let totalExports = 0;
|
|
67
|
-
const domainTerms = [];
|
|
68
|
-
for (const node of ast.body) {
|
|
69
|
-
if (node.type === "ExportAllDeclaration") {
|
|
70
|
-
isBarrel = true;
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
if (node.type === "ExportNamedDeclaration") {
|
|
74
|
-
totalExports++;
|
|
75
|
-
const decl = node.declaration;
|
|
76
|
-
if (decl) {
|
|
77
|
-
const name = decl.id?.name ?? decl.declarations?.[0]?.id?.name;
|
|
78
|
-
if (name) {
|
|
79
|
-
exportedNames.push(name);
|
|
80
|
-
domainTerms.push(
|
|
50
|
+
await parser.initialize();
|
|
51
|
+
const parseResult = parser.parse(code, filePath);
|
|
52
|
+
for (const exp of parseResult.exports) {
|
|
53
|
+
if (exp.type === "function" || exp.type === "class" || exp.type === "const") {
|
|
54
|
+
result.totalExports++;
|
|
55
|
+
const name = exp.name;
|
|
56
|
+
if (name && name !== "default") {
|
|
57
|
+
result.exportedNames.push(name);
|
|
58
|
+
result.domainTerms.push(
|
|
81
59
|
...name.replace(/([A-Z])/g, " $1").toLowerCase().split(/\s+/).filter(Boolean)
|
|
82
60
|
);
|
|
83
|
-
|
|
84
|
-
|
|
61
|
+
if (exp.isTyped === false) {
|
|
62
|
+
result.untypedExports++;
|
|
63
|
+
}
|
|
85
64
|
}
|
|
86
|
-
} else if (node.specifiers && node.specifiers.length > 0) {
|
|
87
|
-
isBarrel = true;
|
|
88
65
|
}
|
|
66
|
+
if (parseResult.exports.length > 5) result.isBarrel = true;
|
|
89
67
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.warn(`Agent Grounding: Failed to parse ${filePath}: ${error}`);
|
|
93
70
|
}
|
|
94
|
-
return
|
|
71
|
+
return result;
|
|
95
72
|
}
|
|
96
73
|
function detectInconsistentTerms(allTerms) {
|
|
97
74
|
const termFreq = /* @__PURE__ */ new Map();
|
|
@@ -160,7 +137,7 @@ async function analyzeAgentGrounding(options) {
|
|
|
160
137
|
"analyzing files",
|
|
161
138
|
options.onProgress
|
|
162
139
|
);
|
|
163
|
-
const analysis = analyzeFile(f);
|
|
140
|
+
const analysis = await analyzeFile(f);
|
|
164
141
|
if (analysis.isBarrel) barrelExports++;
|
|
165
142
|
untypedExports += analysis.untypedExports;
|
|
166
143
|
totalExports += analysis.totalExports;
|
|
@@ -223,11 +200,11 @@ async function analyzeAgentGrounding(options) {
|
|
|
223
200
|
suggestion: "Update README.md to reflect the current codebase structure."
|
|
224
201
|
});
|
|
225
202
|
}
|
|
226
|
-
if (
|
|
203
|
+
if (untypedExports > 0) {
|
|
227
204
|
issues.push({
|
|
228
205
|
type: import_core.IssueType.AgentNavigationFailure,
|
|
229
206
|
dimension: "api-clarity",
|
|
230
|
-
severity: import_core.Severity.Major,
|
|
207
|
+
severity: groundingResult.dimensions.apiClarityScore < 70 ? import_core.Severity.Major : import_core.Severity.Minor,
|
|
231
208
|
message: `${untypedExports} of ${totalExports} public exports lack TypeScript type annotations \u2014 agents cannot infer the API contract.`,
|
|
232
209
|
location: { file: rootDir, line: 0 },
|
|
233
210
|
suggestion: "Add explicit return type and parameter annotations to all exported functions."
|
|
@@ -273,50 +250,28 @@ async function analyzeAgentGrounding(options) {
|
|
|
273
250
|
var import_core2 = require("@aiready/core");
|
|
274
251
|
function calculateGroundingScore(report) {
|
|
275
252
|
const { summary, rawData, recommendations } = report;
|
|
276
|
-
|
|
277
|
-
{
|
|
278
|
-
name: "Structure Clarity",
|
|
279
|
-
impact: Math.round(summary.dimensions.structureClarityScore - 50),
|
|
280
|
-
description: `${rawData.deepDirectories} of ${rawData.totalDirectories} dirs exceed recommended depth`
|
|
281
|
-
},
|
|
282
|
-
{
|
|
283
|
-
name: "Self-Documentation",
|
|
284
|
-
impact: Math.round(summary.dimensions.selfDocumentationScore - 50),
|
|
285
|
-
description: `${rawData.vagueFileNames} of ${rawData.totalFiles} files have vague names`
|
|
286
|
-
},
|
|
287
|
-
{
|
|
288
|
-
name: "Entry Points",
|
|
289
|
-
impact: Math.round(summary.dimensions.entryPointScore - 50),
|
|
290
|
-
description: rawData.hasRootReadme ? rawData.readmeIsFresh ? "README present and fresh" : "README present but stale" : "No root README"
|
|
291
|
-
},
|
|
292
|
-
{
|
|
293
|
-
name: "API Clarity",
|
|
294
|
-
impact: Math.round(summary.dimensions.apiClarityScore - 50),
|
|
295
|
-
description: `${rawData.untypedExports} of ${rawData.totalExports} exports lack type annotations`
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
name: "Domain Consistency",
|
|
299
|
-
impact: Math.round(summary.dimensions.domainConsistencyScore - 50),
|
|
300
|
-
description: `${rawData.inconsistentDomainTerms} inconsistent domain terms detected`
|
|
301
|
-
}
|
|
302
|
-
];
|
|
303
|
-
const recs = recommendations.map(
|
|
304
|
-
(action) => ({
|
|
305
|
-
action,
|
|
306
|
-
estimatedImpact: 6,
|
|
307
|
-
priority: summary.score < 50 ? "high" : "medium"
|
|
308
|
-
})
|
|
309
|
-
);
|
|
310
|
-
return {
|
|
253
|
+
return (0, import_core2.buildStandardToolScore)({
|
|
311
254
|
toolName: import_core2.ToolName.AgentGrounding,
|
|
312
255
|
score: summary.score,
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
256
|
+
rawData,
|
|
257
|
+
dimensions: {
|
|
258
|
+
structureClarityScore: summary.dimensions.structureClarityScore,
|
|
259
|
+
selfDocumentationScore: summary.dimensions.selfDocumentationScore,
|
|
260
|
+
entryPointScore: summary.dimensions.entryPointScore,
|
|
261
|
+
apiClarityScore: summary.dimensions.apiClarityScore,
|
|
262
|
+
domainConsistencyScore: summary.dimensions.domainConsistencyScore
|
|
316
263
|
},
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
264
|
+
dimensionNames: {
|
|
265
|
+
structureClarityScore: "Structure Clarity",
|
|
266
|
+
selfDocumentationScore: "Self-Documentation",
|
|
267
|
+
entryPointScore: "Entry Points",
|
|
268
|
+
apiClarityScore: "API Clarity",
|
|
269
|
+
domainConsistencyScore: "Domain Consistency"
|
|
270
|
+
},
|
|
271
|
+
recommendations,
|
|
272
|
+
recommendationImpact: 6,
|
|
273
|
+
rating: summary.rating
|
|
274
|
+
});
|
|
320
275
|
}
|
|
321
276
|
|
|
322
277
|
// src/cli.ts
|
|
@@ -380,65 +335,41 @@ EXAMPLES:
|
|
|
380
335
|
(0, import_fs2.writeFileSync)(outputPath, JSON.stringify(payload, null, 2));
|
|
381
336
|
console.log(import_chalk.default.green(`\u2713 Report saved to ${outputPath}`));
|
|
382
337
|
} else {
|
|
383
|
-
|
|
338
|
+
(0, import_core3.displayStandardConsoleReport)({
|
|
339
|
+
title: "\u{1F9ED} Agent Grounding Analysis",
|
|
340
|
+
score: scoring.summary.score,
|
|
341
|
+
rating: scoring.summary.rating,
|
|
342
|
+
dimensions: [
|
|
343
|
+
{
|
|
344
|
+
name: "Structure Clarity",
|
|
345
|
+
value: scoring.summary.dimensions.structureClarityScore
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
name: "Self-Documentation",
|
|
349
|
+
value: scoring.summary.dimensions.selfDocumentationScore
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
name: "Entry Points",
|
|
353
|
+
value: scoring.summary.dimensions.entryPointScore
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
name: "API Clarity",
|
|
357
|
+
value: scoring.summary.dimensions.apiClarityScore
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
name: "Domain Consistency",
|
|
361
|
+
value: scoring.summary.dimensions.domainConsistencyScore
|
|
362
|
+
}
|
|
363
|
+
],
|
|
364
|
+
stats: [
|
|
365
|
+
{ label: "Files", value: scoring.summary.filesAnalyzed },
|
|
366
|
+
{ label: "Directories", value: scoring.summary.directoriesAnalyzed }
|
|
367
|
+
],
|
|
368
|
+
issues: report.issues,
|
|
369
|
+
recommendations: report.recommendations,
|
|
370
|
+
elapsedTime: elapsed,
|
|
371
|
+
noIssuesMessage: "\u2728 No grounding issues found \u2014 agents can navigate freely!"
|
|
372
|
+
});
|
|
384
373
|
}
|
|
385
374
|
});
|
|
386
375
|
program.parse();
|
|
387
|
-
function scoreColor(score) {
|
|
388
|
-
if (score >= 85) return import_chalk.default.green;
|
|
389
|
-
if (score >= 70) return import_chalk.default.cyan;
|
|
390
|
-
if (score >= 50) return import_chalk.default.yellow;
|
|
391
|
-
if (score >= 30) return import_chalk.default.red;
|
|
392
|
-
return import_chalk.default.bgRed.white;
|
|
393
|
-
}
|
|
394
|
-
function displayConsoleReport(report, scoring, elapsed) {
|
|
395
|
-
const { summary, issues, recommendations } = report;
|
|
396
|
-
console.log(import_chalk.default.bold("\n\u{1F9ED} Agent Grounding Analysis\n"));
|
|
397
|
-
console.log(
|
|
398
|
-
`Score: ${scoreColor(summary.score)(summary.score + "/100")} (${summary.rating.toUpperCase()})`
|
|
399
|
-
);
|
|
400
|
-
console.log(
|
|
401
|
-
`Files: ${import_chalk.default.cyan(summary.filesAnalyzed)} Directories: ${import_chalk.default.cyan(summary.directoriesAnalyzed)}`
|
|
402
|
-
);
|
|
403
|
-
console.log(`Analysis: ${import_chalk.default.gray(elapsed + "s")}
|
|
404
|
-
`);
|
|
405
|
-
console.log(import_chalk.default.bold("\u{1F4D0} Dimension Scores\n"));
|
|
406
|
-
const dims = [
|
|
407
|
-
["Structure Clarity", summary.dimensions.structureClarityScore],
|
|
408
|
-
["Self-Documentation", summary.dimensions.selfDocumentationScore],
|
|
409
|
-
["Entry Points", summary.dimensions.entryPointScore],
|
|
410
|
-
["API Clarity", summary.dimensions.apiClarityScore],
|
|
411
|
-
["Domain Consistency", summary.dimensions.domainConsistencyScore]
|
|
412
|
-
];
|
|
413
|
-
for (const [name, val] of dims) {
|
|
414
|
-
const bar = "\u2588".repeat(Math.round(val / 10)).padEnd(10, "\u2591");
|
|
415
|
-
console.log(
|
|
416
|
-
` ${String(name).padEnd(22)} ${scoreColor(val)(bar)} ${val}/100`
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
if (issues.length > 0) {
|
|
420
|
-
console.log(import_chalk.default.bold("\n\u26A0\uFE0F Issues Found\n"));
|
|
421
|
-
for (const issue of issues) {
|
|
422
|
-
const sev = issue.severity === "critical" ? import_chalk.default.red : issue.severity === "major" ? import_chalk.default.yellow : import_chalk.default.blue;
|
|
423
|
-
console.log(`${sev(issue.severity.toUpperCase())} ${issue.message}`);
|
|
424
|
-
if (issue.suggestion)
|
|
425
|
-
console.log(
|
|
426
|
-
` ${import_chalk.default.dim("\u2192")} ${import_chalk.default.italic(issue.suggestion)}`
|
|
427
|
-
);
|
|
428
|
-
console.log();
|
|
429
|
-
}
|
|
430
|
-
} else {
|
|
431
|
-
console.log(
|
|
432
|
-
import_chalk.default.green(
|
|
433
|
-
"\n\u2728 No grounding issues found \u2014 agents can navigate freely!\n"
|
|
434
|
-
)
|
|
435
|
-
);
|
|
436
|
-
}
|
|
437
|
-
if (recommendations.length > 0) {
|
|
438
|
-
console.log(import_chalk.default.bold("\u{1F4A1} Recommendations\n"));
|
|
439
|
-
recommendations.forEach(
|
|
440
|
-
(rec, i) => console.log(`${i + 1}. ${rec}`)
|
|
441
|
-
);
|
|
442
|
-
}
|
|
443
|
-
console.log();
|
|
444
|
-
}
|
package/dist/cli.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
analyzeAgentGrounding,
|
|
4
4
|
calculateGroundingScore
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-OFAWUHBZ.mjs";
|
|
6
6
|
|
|
7
7
|
// src/cli.ts
|
|
8
8
|
import { Command } from "commander";
|
|
@@ -12,7 +12,8 @@ import { dirname } from "path";
|
|
|
12
12
|
import {
|
|
13
13
|
loadConfig,
|
|
14
14
|
mergeConfigWithDefaults,
|
|
15
|
-
resolveOutputPath
|
|
15
|
+
resolveOutputPath,
|
|
16
|
+
displayStandardConsoleReport
|
|
16
17
|
} from "@aiready/core";
|
|
17
18
|
var program = new Command();
|
|
18
19
|
program.name("aiready-agent-grounding").description(
|
|
@@ -70,65 +71,41 @@ EXAMPLES:
|
|
|
70
71
|
writeFileSync(outputPath, JSON.stringify(payload, null, 2));
|
|
71
72
|
console.log(chalk.green(`\u2713 Report saved to ${outputPath}`));
|
|
72
73
|
} else {
|
|
73
|
-
|
|
74
|
+
displayStandardConsoleReport({
|
|
75
|
+
title: "\u{1F9ED} Agent Grounding Analysis",
|
|
76
|
+
score: scoring.summary.score,
|
|
77
|
+
rating: scoring.summary.rating,
|
|
78
|
+
dimensions: [
|
|
79
|
+
{
|
|
80
|
+
name: "Structure Clarity",
|
|
81
|
+
value: scoring.summary.dimensions.structureClarityScore
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "Self-Documentation",
|
|
85
|
+
value: scoring.summary.dimensions.selfDocumentationScore
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "Entry Points",
|
|
89
|
+
value: scoring.summary.dimensions.entryPointScore
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "API Clarity",
|
|
93
|
+
value: scoring.summary.dimensions.apiClarityScore
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "Domain Consistency",
|
|
97
|
+
value: scoring.summary.dimensions.domainConsistencyScore
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
stats: [
|
|
101
|
+
{ label: "Files", value: scoring.summary.filesAnalyzed },
|
|
102
|
+
{ label: "Directories", value: scoring.summary.directoriesAnalyzed }
|
|
103
|
+
],
|
|
104
|
+
issues: report.issues,
|
|
105
|
+
recommendations: report.recommendations,
|
|
106
|
+
elapsedTime: elapsed,
|
|
107
|
+
noIssuesMessage: "\u2728 No grounding issues found \u2014 agents can navigate freely!"
|
|
108
|
+
});
|
|
74
109
|
}
|
|
75
110
|
});
|
|
76
111
|
program.parse();
|
|
77
|
-
function scoreColor(score) {
|
|
78
|
-
if (score >= 85) return chalk.green;
|
|
79
|
-
if (score >= 70) return chalk.cyan;
|
|
80
|
-
if (score >= 50) return chalk.yellow;
|
|
81
|
-
if (score >= 30) return chalk.red;
|
|
82
|
-
return chalk.bgRed.white;
|
|
83
|
-
}
|
|
84
|
-
function displayConsoleReport(report, scoring, elapsed) {
|
|
85
|
-
const { summary, issues, recommendations } = report;
|
|
86
|
-
console.log(chalk.bold("\n\u{1F9ED} Agent Grounding Analysis\n"));
|
|
87
|
-
console.log(
|
|
88
|
-
`Score: ${scoreColor(summary.score)(summary.score + "/100")} (${summary.rating.toUpperCase()})`
|
|
89
|
-
);
|
|
90
|
-
console.log(
|
|
91
|
-
`Files: ${chalk.cyan(summary.filesAnalyzed)} Directories: ${chalk.cyan(summary.directoriesAnalyzed)}`
|
|
92
|
-
);
|
|
93
|
-
console.log(`Analysis: ${chalk.gray(elapsed + "s")}
|
|
94
|
-
`);
|
|
95
|
-
console.log(chalk.bold("\u{1F4D0} Dimension Scores\n"));
|
|
96
|
-
const dims = [
|
|
97
|
-
["Structure Clarity", summary.dimensions.structureClarityScore],
|
|
98
|
-
["Self-Documentation", summary.dimensions.selfDocumentationScore],
|
|
99
|
-
["Entry Points", summary.dimensions.entryPointScore],
|
|
100
|
-
["API Clarity", summary.dimensions.apiClarityScore],
|
|
101
|
-
["Domain Consistency", summary.dimensions.domainConsistencyScore]
|
|
102
|
-
];
|
|
103
|
-
for (const [name, val] of dims) {
|
|
104
|
-
const bar = "\u2588".repeat(Math.round(val / 10)).padEnd(10, "\u2591");
|
|
105
|
-
console.log(
|
|
106
|
-
` ${String(name).padEnd(22)} ${scoreColor(val)(bar)} ${val}/100`
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
if (issues.length > 0) {
|
|
110
|
-
console.log(chalk.bold("\n\u26A0\uFE0F Issues Found\n"));
|
|
111
|
-
for (const issue of issues) {
|
|
112
|
-
const sev = issue.severity === "critical" ? chalk.red : issue.severity === "major" ? chalk.yellow : chalk.blue;
|
|
113
|
-
console.log(`${sev(issue.severity.toUpperCase())} ${issue.message}`);
|
|
114
|
-
if (issue.suggestion)
|
|
115
|
-
console.log(
|
|
116
|
-
` ${chalk.dim("\u2192")} ${chalk.italic(issue.suggestion)}`
|
|
117
|
-
);
|
|
118
|
-
console.log();
|
|
119
|
-
}
|
|
120
|
-
} else {
|
|
121
|
-
console.log(
|
|
122
|
-
chalk.green(
|
|
123
|
-
"\n\u2728 No grounding issues found \u2014 agents can navigate freely!\n"
|
|
124
|
-
)
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
if (recommendations.length > 0) {
|
|
128
|
-
console.log(chalk.bold("\u{1F4A1} Recommendations\n"));
|
|
129
|
-
recommendations.forEach(
|
|
130
|
-
(rec, i) => console.log(`${i + 1}. ${rec}`)
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
console.log();
|
|
134
|
-
}
|