@aiready/core 0.9.37 → 0.9.38
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-UIWL5JQB.mjs +410 -0
- package/dist/chunk-UQGI67WR.mjs +410 -0
- package/dist/client.js +4 -4
- package/dist/client.mjs +1 -1
- package/dist/index.js +22 -16
- package/dist/index.mjs +10 -4
- package/package.json +2 -1
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
// src/types/language.ts
|
|
2
|
+
var Language = /* @__PURE__ */ ((Language2) => {
|
|
3
|
+
Language2["TypeScript"] = "typescript";
|
|
4
|
+
Language2["JavaScript"] = "javascript";
|
|
5
|
+
Language2["Python"] = "python";
|
|
6
|
+
Language2["Java"] = "java";
|
|
7
|
+
Language2["Go"] = "go";
|
|
8
|
+
Language2["Rust"] = "rust";
|
|
9
|
+
Language2["CSharp"] = "csharp";
|
|
10
|
+
return Language2;
|
|
11
|
+
})(Language || {});
|
|
12
|
+
var LANGUAGE_EXTENSIONS = {
|
|
13
|
+
".ts": "typescript" /* TypeScript */,
|
|
14
|
+
".tsx": "typescript" /* TypeScript */,
|
|
15
|
+
".js": "javascript" /* JavaScript */,
|
|
16
|
+
".jsx": "javascript" /* JavaScript */,
|
|
17
|
+
".py": "python" /* Python */,
|
|
18
|
+
".java": "java" /* Java */,
|
|
19
|
+
".go": "go" /* Go */,
|
|
20
|
+
".rs": "rust" /* Rust */,
|
|
21
|
+
".cs": "csharp" /* CSharp */
|
|
22
|
+
};
|
|
23
|
+
var ParseError = class extends Error {
|
|
24
|
+
constructor(message, filePath, loc) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.filePath = filePath;
|
|
27
|
+
this.loc = loc;
|
|
28
|
+
this.name = "ParseError";
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// src/scoring.ts
|
|
33
|
+
var DEFAULT_TOOL_WEIGHTS = {
|
|
34
|
+
"pattern-detect": 22,
|
|
35
|
+
"context-analyzer": 19,
|
|
36
|
+
consistency: 14,
|
|
37
|
+
"ai-signal-clarity": 11,
|
|
38
|
+
"agent-grounding": 10,
|
|
39
|
+
testability: 10,
|
|
40
|
+
"doc-drift": 8,
|
|
41
|
+
deps: 6
|
|
42
|
+
};
|
|
43
|
+
var TOOL_NAME_MAP = {
|
|
44
|
+
patterns: "pattern-detect",
|
|
45
|
+
context: "context-analyzer",
|
|
46
|
+
consistency: "consistency",
|
|
47
|
+
"AI signal clarity": "ai-signal-clarity",
|
|
48
|
+
"ai-signal-clarity": "ai-signal-clarity",
|
|
49
|
+
grounding: "agent-grounding",
|
|
50
|
+
"agent-grounding": "agent-grounding",
|
|
51
|
+
testability: "testability",
|
|
52
|
+
tests: "testability",
|
|
53
|
+
"doc-drift": "doc-drift",
|
|
54
|
+
docs: "doc-drift",
|
|
55
|
+
deps: "deps"
|
|
56
|
+
};
|
|
57
|
+
var CONTEXT_TIER_THRESHOLDS = {
|
|
58
|
+
compact: { idealTokens: 3e3, criticalTokens: 1e4, idealDepth: 4 },
|
|
59
|
+
standard: { idealTokens: 5e3, criticalTokens: 15e3, idealDepth: 5 },
|
|
60
|
+
extended: { idealTokens: 15e3, criticalTokens: 5e4, idealDepth: 7 },
|
|
61
|
+
frontier: { idealTokens: 5e4, criticalTokens: 15e4, idealDepth: 10 }
|
|
62
|
+
};
|
|
63
|
+
var SIZE_ADJUSTED_THRESHOLDS = {
|
|
64
|
+
xs: 80,
|
|
65
|
+
// < 50 files
|
|
66
|
+
small: 75,
|
|
67
|
+
// 50-200 files
|
|
68
|
+
medium: 70,
|
|
69
|
+
// 200-500 files
|
|
70
|
+
large: 65,
|
|
71
|
+
// 500-2000 files
|
|
72
|
+
enterprise: 58
|
|
73
|
+
// 2000+ files
|
|
74
|
+
};
|
|
75
|
+
function getProjectSizeTier(fileCount) {
|
|
76
|
+
if (fileCount < 50) return "xs";
|
|
77
|
+
if (fileCount < 200) return "small";
|
|
78
|
+
if (fileCount < 500) return "medium";
|
|
79
|
+
if (fileCount < 2e3) return "large";
|
|
80
|
+
return "enterprise";
|
|
81
|
+
}
|
|
82
|
+
function getRecommendedThreshold(fileCount, modelTier = "standard") {
|
|
83
|
+
const sizeTier = getProjectSizeTier(fileCount);
|
|
84
|
+
const base = SIZE_ADJUSTED_THRESHOLDS[sizeTier];
|
|
85
|
+
const modelBonus = modelTier === "frontier" ? -3 : modelTier === "extended" ? -2 : 0;
|
|
86
|
+
return base + modelBonus;
|
|
87
|
+
}
|
|
88
|
+
function normalizeToolName(shortName) {
|
|
89
|
+
return TOOL_NAME_MAP[shortName] || shortName;
|
|
90
|
+
}
|
|
91
|
+
function getToolWeight(toolName, toolConfig, cliOverride) {
|
|
92
|
+
if (cliOverride !== void 0) {
|
|
93
|
+
return cliOverride;
|
|
94
|
+
}
|
|
95
|
+
if (toolConfig?.scoreWeight !== void 0) {
|
|
96
|
+
return toolConfig.scoreWeight;
|
|
97
|
+
}
|
|
98
|
+
return DEFAULT_TOOL_WEIGHTS[toolName] || 5;
|
|
99
|
+
}
|
|
100
|
+
function parseWeightString(weightStr) {
|
|
101
|
+
const weights = /* @__PURE__ */ new Map();
|
|
102
|
+
if (!weightStr) {
|
|
103
|
+
return weights;
|
|
104
|
+
}
|
|
105
|
+
const pairs = weightStr.split(",");
|
|
106
|
+
for (const pair of pairs) {
|
|
107
|
+
const [toolShortName, weightStr2] = pair.split(":");
|
|
108
|
+
if (toolShortName && weightStr2) {
|
|
109
|
+
const toolName = normalizeToolName(toolShortName.trim());
|
|
110
|
+
const weight = parseInt(weightStr2.trim(), 10);
|
|
111
|
+
if (!isNaN(weight) && weight > 0) {
|
|
112
|
+
weights.set(toolName, weight);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return weights;
|
|
117
|
+
}
|
|
118
|
+
function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
119
|
+
if (toolOutputs.size === 0) {
|
|
120
|
+
throw new Error("No tool outputs provided for scoring");
|
|
121
|
+
}
|
|
122
|
+
const weights = /* @__PURE__ */ new Map();
|
|
123
|
+
for (const [toolName] of toolOutputs.entries()) {
|
|
124
|
+
const cliWeight = cliWeights?.get(toolName);
|
|
125
|
+
const configWeight = config?.tools?.[toolName]?.scoreWeight;
|
|
126
|
+
const weight = cliWeight ?? configWeight ?? DEFAULT_TOOL_WEIGHTS[toolName] ?? 5;
|
|
127
|
+
weights.set(toolName, weight);
|
|
128
|
+
}
|
|
129
|
+
let weightedSum = 0;
|
|
130
|
+
let totalWeight = 0;
|
|
131
|
+
const breakdown = [];
|
|
132
|
+
const toolsUsed = [];
|
|
133
|
+
const calculationWeights = {};
|
|
134
|
+
for (const [toolName, output] of toolOutputs.entries()) {
|
|
135
|
+
const weight = weights.get(toolName) || 5;
|
|
136
|
+
const weightedScore = output.score * weight;
|
|
137
|
+
weightedSum += weightedScore;
|
|
138
|
+
totalWeight += weight;
|
|
139
|
+
toolsUsed.push(toolName);
|
|
140
|
+
calculationWeights[toolName] = weight;
|
|
141
|
+
breakdown.push(output);
|
|
142
|
+
}
|
|
143
|
+
const overall = Math.round(weightedSum / totalWeight);
|
|
144
|
+
const rating = getRating(overall);
|
|
145
|
+
const formulaParts = Array.from(toolOutputs.entries()).map(
|
|
146
|
+
([name, output]) => {
|
|
147
|
+
const w = weights.get(name) || 5;
|
|
148
|
+
return `(${output.score} \xD7 ${w})`;
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
const formulaStr = `[${formulaParts.join(" + ")}] / ${totalWeight} = ${overall}`;
|
|
152
|
+
return {
|
|
153
|
+
overall,
|
|
154
|
+
rating,
|
|
155
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
156
|
+
toolsUsed,
|
|
157
|
+
breakdown,
|
|
158
|
+
calculation: {
|
|
159
|
+
formula: formulaStr,
|
|
160
|
+
weights: calculationWeights,
|
|
161
|
+
normalized: formulaStr
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function getRating(score) {
|
|
166
|
+
if (score >= 90) return "Excellent";
|
|
167
|
+
if (score >= 75) return "Good";
|
|
168
|
+
if (score >= 60) return "Fair";
|
|
169
|
+
if (score >= 40) return "Needs Work";
|
|
170
|
+
return "Critical";
|
|
171
|
+
}
|
|
172
|
+
function getRatingWithContext(score, fileCount, modelTier = "standard") {
|
|
173
|
+
const threshold = getRecommendedThreshold(fileCount, modelTier);
|
|
174
|
+
const normalized = score - threshold + 70;
|
|
175
|
+
return getRating(normalized);
|
|
176
|
+
}
|
|
177
|
+
function getRatingDisplay(rating) {
|
|
178
|
+
switch (rating) {
|
|
179
|
+
case "Excellent":
|
|
180
|
+
return { emoji: "\u2705", color: "green" };
|
|
181
|
+
case "Good":
|
|
182
|
+
return { emoji: "\u{1F44D}", color: "blue" };
|
|
183
|
+
case "Fair":
|
|
184
|
+
return { emoji: "\u26A0\uFE0F", color: "yellow" };
|
|
185
|
+
case "Needs Work":
|
|
186
|
+
return { emoji: "\u{1F528}", color: "orange" };
|
|
187
|
+
case "Critical":
|
|
188
|
+
return { emoji: "\u274C", color: "red" };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function formatScore(result) {
|
|
192
|
+
const { emoji, color } = getRatingDisplay(result.rating);
|
|
193
|
+
return `${result.overall}/100 (${result.rating}) ${emoji}`;
|
|
194
|
+
}
|
|
195
|
+
function formatToolScore(output) {
|
|
196
|
+
let result = ` Score: ${output.score}/100
|
|
197
|
+
|
|
198
|
+
`;
|
|
199
|
+
if (output.factors && output.factors.length > 0) {
|
|
200
|
+
result += ` Factors:
|
|
201
|
+
`;
|
|
202
|
+
output.factors.forEach((factor) => {
|
|
203
|
+
const impactSign = factor.impact > 0 ? "+" : "";
|
|
204
|
+
result += ` \u2022 ${factor.name}: ${impactSign}${factor.impact} - ${factor.description}
|
|
205
|
+
`;
|
|
206
|
+
});
|
|
207
|
+
result += "\n";
|
|
208
|
+
}
|
|
209
|
+
if (output.recommendations && output.recommendations.length > 0) {
|
|
210
|
+
result += ` Recommendations:
|
|
211
|
+
`;
|
|
212
|
+
output.recommendations.forEach((rec, i) => {
|
|
213
|
+
const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
|
|
214
|
+
result += ` ${i + 1}. ${priorityIcon} ${rec.action}
|
|
215
|
+
`;
|
|
216
|
+
result += ` Impact: +${rec.estimatedImpact} points
|
|
217
|
+
|
|
218
|
+
`;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// src/utils/visualization.ts
|
|
225
|
+
function generateHTML(graph) {
|
|
226
|
+
const payload = JSON.stringify(graph, null, 2);
|
|
227
|
+
return `<!doctype html>
|
|
228
|
+
<html>
|
|
229
|
+
<head>
|
|
230
|
+
<meta charset="utf-8" />
|
|
231
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
232
|
+
<title>AIReady Visualization</title>
|
|
233
|
+
<style>
|
|
234
|
+
html,body { height: 100%; margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0 }
|
|
235
|
+
#container { display:flex; height:100vh }
|
|
236
|
+
#panel { width: 320px; padding: 16px; background: #071130; box-shadow: -2px 0 8px rgba(0,0,0,0.3); overflow:auto }
|
|
237
|
+
#canvasWrap { flex:1; display:flex; align-items:center; justify-content:center }
|
|
238
|
+
canvas { background: #0b1220; border-radius:8px }
|
|
239
|
+
.stat { margin-bottom:12px }
|
|
240
|
+
</style>
|
|
241
|
+
</head>
|
|
242
|
+
<body>
|
|
243
|
+
<div id="container">
|
|
244
|
+
<div id="canvasWrap"><canvas id="canvas" width="1200" height="800"></canvas></div>
|
|
245
|
+
<div id="panel">
|
|
246
|
+
<h2>AIReady Visualization</h2>
|
|
247
|
+
<div class="stat"><strong>Files:</strong> <span id="stat-files"></span></div>
|
|
248
|
+
<div class="stat"><strong>Dependencies:</strong> <span id="stat-deps"></span></div>
|
|
249
|
+
<div class="stat"><strong>Legend</strong></div>
|
|
250
|
+
<div style="font-size:13px;line-height:1.3;color:#cbd5e1;margin-top:8px">
|
|
251
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ff4d4f;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Critical</strong>: highest severity issues.</div>
|
|
252
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ff9900;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Major</strong>: important issues.</div>
|
|
253
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ffd666;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Minor</strong>: low priority issues.</div>
|
|
254
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#91d5ff;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Info</strong>: informational notes.</div>
|
|
255
|
+
<div style="margin-top:10px;color:#94a3b8"><strong>Node size</strong>: larger = higher token cost, more issues or dependency weight.</div>
|
|
256
|
+
<div style="margin-top:6px;color:#94a3b8"><strong>Proximity</strong>: nodes that are spatially close are more contextually related; relatedness is represented by distance and size rather than explicit edges.</div>
|
|
257
|
+
<div style="margin-top:6px;color:#94a3b8"><strong>Edge colors</strong>: <span style="color:#fb7e81">Similarity</span>, <span style="color:#84c1ff">Dependency</span>, <span style="color:#ffa500">Reference</span>, default <span style="color:#334155">Other</span>.</div>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
|
|
262
|
+
<script>
|
|
263
|
+
const graphData = ${payload};
|
|
264
|
+
document.getElementById('stat-files').textContent = graphData.metadata.totalFiles;
|
|
265
|
+
document.getElementById('stat-deps').textContent = graphData.metadata.totalDependencies;
|
|
266
|
+
|
|
267
|
+
const canvas = document.getElementById('canvas');
|
|
268
|
+
const ctx = canvas.getContext('2d');
|
|
269
|
+
|
|
270
|
+
const nodes = graphData.nodes.map((n, i) => ({
|
|
271
|
+
...n,
|
|
272
|
+
x: canvas.width / 2 + Math.cos(i / graphData.nodes.length * Math.PI * 2) * (Math.min(canvas.width, canvas.height) / 3),
|
|
273
|
+
y: canvas.height / 2 + Math.sin(i / graphData.nodes.length * Math.PI * 2) * (Math.min(canvas.width, canvas.height) / 3),
|
|
274
|
+
}));
|
|
275
|
+
|
|
276
|
+
function draw() {
|
|
277
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
278
|
+
|
|
279
|
+
graphData.edges.forEach(edge => {
|
|
280
|
+
const s = nodes.find(n => n.id === edge.source);
|
|
281
|
+
const t = nodes.find(n => n.id === edge.target);
|
|
282
|
+
if (!s || !t) return;
|
|
283
|
+
if (edge.type === 'related') return;
|
|
284
|
+
if (edge.type === 'similarity') {
|
|
285
|
+
ctx.strokeStyle = '#fb7e81';
|
|
286
|
+
ctx.lineWidth = 1.2;
|
|
287
|
+
} else if (edge.type === 'dependency') {
|
|
288
|
+
ctx.strokeStyle = '#84c1ff';
|
|
289
|
+
ctx.lineWidth = 1.0;
|
|
290
|
+
} else if (edge.type === 'reference') {
|
|
291
|
+
ctx.strokeStyle = '#ffa500';
|
|
292
|
+
ctx.lineWidth = 0.9;
|
|
293
|
+
} else {
|
|
294
|
+
ctx.strokeStyle = '#334155';
|
|
295
|
+
ctx.lineWidth = 0.8;
|
|
296
|
+
}
|
|
297
|
+
ctx.beginPath();
|
|
298
|
+
ctx.moveTo(s.x, s.y);
|
|
299
|
+
ctx.lineTo(t.x, t.y);
|
|
300
|
+
ctx.stroke();
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
const groups = {};
|
|
304
|
+
nodes.forEach(n => {
|
|
305
|
+
const g = n.group || '__default';
|
|
306
|
+
if (!groups[g]) groups[g] = { minX: n.x, minY: n.y, maxX: n.x, maxY: n.y };
|
|
307
|
+
groups[g].minX = Math.min(groups[g].minX, n.x);
|
|
308
|
+
groups[g].minY = Math.min(groups[g].minY, n.y);
|
|
309
|
+
groups[g].maxX = Math.max(groups[g].maxX, n.x);
|
|
310
|
+
groups[g].maxY = Math.max(groups[g].maxY, n.y);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const groupRelations = {};
|
|
314
|
+
graphData.edges.forEach(edge => {
|
|
315
|
+
const sNode = nodes.find(n => n.id === edge.source);
|
|
316
|
+
const tNode = nodes.find(n => n.id === edge.target);
|
|
317
|
+
if (!sNode || !tNode) return;
|
|
318
|
+
const g1 = sNode.group || '__default';
|
|
319
|
+
const g2 = tNode.group || '__default';
|
|
320
|
+
if (g1 === g2) return;
|
|
321
|
+
const key = g1 < g2 ? g1 + '::' + g2 : g2 + '::' + g1;
|
|
322
|
+
groupRelations[key] = (groupRelations[key] || 0) + 1;
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
Object.keys(groupRelations).forEach(k => {
|
|
326
|
+
const count = groupRelations[k];
|
|
327
|
+
const [ga, gb] = k.split('::');
|
|
328
|
+
if (!groups[ga] || !groups[gb]) return;
|
|
329
|
+
const ax = (groups[ga].minX + groups[ga].maxX) / 2;
|
|
330
|
+
const ay = (groups[ga].minY + groups[ga].maxY) / 2;
|
|
331
|
+
const bx = (groups[gb].minX + groups[gb].maxX) / 2;
|
|
332
|
+
const by = (groups[gb].minY + groups[gb].maxY) / 2;
|
|
333
|
+
ctx.beginPath();
|
|
334
|
+
ctx.strokeStyle = 'rgba(148,163,184,0.25)';
|
|
335
|
+
ctx.lineWidth = Math.min(6, 0.6 + Math.sqrt(count));
|
|
336
|
+
ctx.moveTo(ax, ay);
|
|
337
|
+
ctx.lineTo(bx, by);
|
|
338
|
+
ctx.stroke();
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
Object.keys(groups).forEach(g => {
|
|
342
|
+
if (g === '__default') return;
|
|
343
|
+
const box = groups[g];
|
|
344
|
+
const pad = 16;
|
|
345
|
+
const x = box.minX - pad;
|
|
346
|
+
const y = box.minY - pad;
|
|
347
|
+
const w = (box.maxX - box.minX) + pad * 2;
|
|
348
|
+
const h = (box.maxY - box.minY) + pad * 2;
|
|
349
|
+
ctx.save();
|
|
350
|
+
ctx.fillStyle = 'rgba(30,64,175,0.04)';
|
|
351
|
+
ctx.strokeStyle = 'rgba(30,64,175,0.12)';
|
|
352
|
+
ctx.lineWidth = 1.2;
|
|
353
|
+
const r = 8;
|
|
354
|
+
ctx.beginPath();
|
|
355
|
+
ctx.moveTo(x + r, y);
|
|
356
|
+
ctx.arcTo(x + w, y, x + w, y + h, r);
|
|
357
|
+
ctx.arcTo(x + w, y + h, x, y + h, r);
|
|
358
|
+
ctx.arcTo(x, y + h, x, y, r);
|
|
359
|
+
ctx.arcTo(x, y, x + w, y, r);
|
|
360
|
+
ctx.closePath();
|
|
361
|
+
ctx.fill();
|
|
362
|
+
ctx.stroke();
|
|
363
|
+
ctx.restore();
|
|
364
|
+
ctx.fillStyle = '#94a3b8';
|
|
365
|
+
ctx.font = '11px sans-serif';
|
|
366
|
+
ctx.fillText(g, x + 8, y + 14);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
nodes.forEach(n => {
|
|
370
|
+
const sizeVal = (n.size || n.value || 1);
|
|
371
|
+
const r = 6 + (sizeVal / 2);
|
|
372
|
+
ctx.beginPath();
|
|
373
|
+
ctx.fillStyle = n.color || '#60a5fa';
|
|
374
|
+
ctx.arc(n.x, n.y, r, 0, Math.PI * 2);
|
|
375
|
+
ctx.fill();
|
|
376
|
+
|
|
377
|
+
ctx.fillStyle = '#e2e8f0';
|
|
378
|
+
ctx.font = '11px sans-serif';
|
|
379
|
+
ctx.textAlign = 'center';
|
|
380
|
+
ctx.fillText(n.label || n.id.split('/').slice(-1)[0], n.x, n.y + r + 12);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
draw();
|
|
385
|
+
</script>
|
|
386
|
+
</body>
|
|
387
|
+
</html>`;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export {
|
|
391
|
+
Language,
|
|
392
|
+
LANGUAGE_EXTENSIONS,
|
|
393
|
+
ParseError,
|
|
394
|
+
DEFAULT_TOOL_WEIGHTS,
|
|
395
|
+
TOOL_NAME_MAP,
|
|
396
|
+
CONTEXT_TIER_THRESHOLDS,
|
|
397
|
+
SIZE_ADJUSTED_THRESHOLDS,
|
|
398
|
+
getProjectSizeTier,
|
|
399
|
+
getRecommendedThreshold,
|
|
400
|
+
normalizeToolName,
|
|
401
|
+
getToolWeight,
|
|
402
|
+
parseWeightString,
|
|
403
|
+
calculateOverallScore,
|
|
404
|
+
getRating,
|
|
405
|
+
getRatingWithContext,
|
|
406
|
+
getRatingDisplay,
|
|
407
|
+
formatScore,
|
|
408
|
+
formatToolScore,
|
|
409
|
+
generateHTML
|
|
410
|
+
};
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
// src/types/language.ts
|
|
2
|
+
var Language = /* @__PURE__ */ ((Language2) => {
|
|
3
|
+
Language2["TypeScript"] = "typescript";
|
|
4
|
+
Language2["JavaScript"] = "javascript";
|
|
5
|
+
Language2["Python"] = "python";
|
|
6
|
+
Language2["Java"] = "java";
|
|
7
|
+
Language2["Go"] = "go";
|
|
8
|
+
Language2["Rust"] = "rust";
|
|
9
|
+
Language2["CSharp"] = "csharp";
|
|
10
|
+
return Language2;
|
|
11
|
+
})(Language || {});
|
|
12
|
+
var LANGUAGE_EXTENSIONS = {
|
|
13
|
+
".ts": "typescript" /* TypeScript */,
|
|
14
|
+
".tsx": "typescript" /* TypeScript */,
|
|
15
|
+
".js": "javascript" /* JavaScript */,
|
|
16
|
+
".jsx": "javascript" /* JavaScript */,
|
|
17
|
+
".py": "python" /* Python */,
|
|
18
|
+
".java": "java" /* Java */,
|
|
19
|
+
".go": "go" /* Go */,
|
|
20
|
+
".rs": "rust" /* Rust */,
|
|
21
|
+
".cs": "csharp" /* CSharp */
|
|
22
|
+
};
|
|
23
|
+
var ParseError = class extends Error {
|
|
24
|
+
constructor(message, filePath, loc) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.filePath = filePath;
|
|
27
|
+
this.loc = loc;
|
|
28
|
+
this.name = "ParseError";
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// src/scoring.ts
|
|
33
|
+
var DEFAULT_TOOL_WEIGHTS = {
|
|
34
|
+
"pattern-detect": 22,
|
|
35
|
+
"context-analyzer": 19,
|
|
36
|
+
consistency: 14,
|
|
37
|
+
"ai-signal-clarity": 11,
|
|
38
|
+
"agent-grounding": 10,
|
|
39
|
+
testability: 10,
|
|
40
|
+
"doc-drift": 8,
|
|
41
|
+
deps: 6
|
|
42
|
+
};
|
|
43
|
+
var TOOL_NAME_MAP = {
|
|
44
|
+
patterns: "pattern-detect",
|
|
45
|
+
context: "context-analyzer",
|
|
46
|
+
consistency: "consistency",
|
|
47
|
+
"AI signal clarity": "ai-signal-clarity",
|
|
48
|
+
"ai-signal-clarity": "ai-signal-clarity",
|
|
49
|
+
grounding: "agent-grounding",
|
|
50
|
+
"agent-grounding": "agent-grounding",
|
|
51
|
+
testability: "testability",
|
|
52
|
+
tests: "testability",
|
|
53
|
+
"doc-drift": "doc-drift",
|
|
54
|
+
docs: "doc-drift",
|
|
55
|
+
deps: "deps"
|
|
56
|
+
};
|
|
57
|
+
var CONTEXT_TIER_THRESHOLDS = {
|
|
58
|
+
compact: { idealTokens: 3e3, criticalTokens: 1e4, idealDepth: 4 },
|
|
59
|
+
standard: { idealTokens: 5e3, criticalTokens: 15e3, idealDepth: 5 },
|
|
60
|
+
extended: { idealTokens: 15e3, criticalTokens: 5e4, idealDepth: 7 },
|
|
61
|
+
frontier: { idealTokens: 5e4, criticalTokens: 15e4, idealDepth: 10 }
|
|
62
|
+
};
|
|
63
|
+
var SIZE_ADJUSTED_THRESHOLDS = {
|
|
64
|
+
xs: 80,
|
|
65
|
+
// < 50 files
|
|
66
|
+
small: 75,
|
|
67
|
+
// 50-200 files
|
|
68
|
+
medium: 70,
|
|
69
|
+
// 200-500 files
|
|
70
|
+
large: 65,
|
|
71
|
+
// 500-2000 files
|
|
72
|
+
enterprise: 58
|
|
73
|
+
// 2000+ files
|
|
74
|
+
};
|
|
75
|
+
function getProjectSizeTier(fileCount) {
|
|
76
|
+
if (fileCount < 50) return "xs";
|
|
77
|
+
if (fileCount < 200) return "small";
|
|
78
|
+
if (fileCount < 500) return "medium";
|
|
79
|
+
if (fileCount < 2e3) return "large";
|
|
80
|
+
return "enterprise";
|
|
81
|
+
}
|
|
82
|
+
function getRecommendedThreshold(fileCount, modelTier = "standard") {
|
|
83
|
+
const sizeTier = getProjectSizeTier(fileCount);
|
|
84
|
+
const base = SIZE_ADJUSTED_THRESHOLDS[sizeTier];
|
|
85
|
+
const modelBonus = modelTier === "frontier" ? -3 : modelTier === "extended" ? -2 : 0;
|
|
86
|
+
return base + modelBonus;
|
|
87
|
+
}
|
|
88
|
+
function normalizeToolName(shortName) {
|
|
89
|
+
return TOOL_NAME_MAP[shortName] || shortName;
|
|
90
|
+
}
|
|
91
|
+
function getToolWeight(toolName, toolConfig, cliOverride) {
|
|
92
|
+
if (cliOverride !== void 0) {
|
|
93
|
+
return cliOverride;
|
|
94
|
+
}
|
|
95
|
+
if (toolConfig?.scoreWeight !== void 0) {
|
|
96
|
+
return toolConfig.scoreWeight;
|
|
97
|
+
}
|
|
98
|
+
return DEFAULT_TOOL_WEIGHTS[toolName] || 5;
|
|
99
|
+
}
|
|
100
|
+
function parseWeightString(weightStr) {
|
|
101
|
+
const weights = /* @__PURE__ */ new Map();
|
|
102
|
+
if (!weightStr) {
|
|
103
|
+
return weights;
|
|
104
|
+
}
|
|
105
|
+
const pairs = weightStr.split(",");
|
|
106
|
+
for (const pair of pairs) {
|
|
107
|
+
const [toolShortName, weightStr2] = pair.split(":");
|
|
108
|
+
if (toolShortName && weightStr2) {
|
|
109
|
+
const toolName = normalizeToolName(toolShortName.trim());
|
|
110
|
+
const weight = parseInt(weightStr2.trim(), 10);
|
|
111
|
+
if (!isNaN(weight) && weight > 0) {
|
|
112
|
+
weights.set(toolName, weight);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return weights;
|
|
117
|
+
}
|
|
118
|
+
function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
119
|
+
if (toolOutputs.size === 0) {
|
|
120
|
+
throw new Error("No tool outputs provided for scoring");
|
|
121
|
+
}
|
|
122
|
+
const weights = /* @__PURE__ */ new Map();
|
|
123
|
+
for (const [toolName] of toolOutputs.entries()) {
|
|
124
|
+
const cliWeight = cliWeights?.get(toolName);
|
|
125
|
+
const configWeight = config?.tools?.[toolName]?.scoreWeight;
|
|
126
|
+
const weight = cliWeight ?? configWeight ?? DEFAULT_TOOL_WEIGHTS[toolName] ?? 5;
|
|
127
|
+
weights.set(toolName, weight);
|
|
128
|
+
}
|
|
129
|
+
let weightedSum = 0;
|
|
130
|
+
let totalWeight = 0;
|
|
131
|
+
const breakdown = [];
|
|
132
|
+
const toolsUsed = [];
|
|
133
|
+
const calculationWeights = {};
|
|
134
|
+
for (const [toolName, output] of toolOutputs.entries()) {
|
|
135
|
+
const weight = weights.get(toolName) || 5;
|
|
136
|
+
const weightedScore = output.score * weight;
|
|
137
|
+
weightedSum += weightedScore;
|
|
138
|
+
totalWeight += weight;
|
|
139
|
+
toolsUsed.push(toolName);
|
|
140
|
+
calculationWeights[toolName] = weight;
|
|
141
|
+
breakdown.push(output);
|
|
142
|
+
}
|
|
143
|
+
const overall = Math.round(weightedSum / totalWeight);
|
|
144
|
+
const rating = getRating(overall);
|
|
145
|
+
const formulaParts = Array.from(toolOutputs.entries()).map(
|
|
146
|
+
([name, output]) => {
|
|
147
|
+
const w = weights.get(name) || 5;
|
|
148
|
+
return `(${output.score} \xD7 ${w})`;
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
const formulaStr = `[${formulaParts.join(" + ")}] / ${totalWeight} = ${overall}`;
|
|
152
|
+
return {
|
|
153
|
+
overall,
|
|
154
|
+
rating,
|
|
155
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
156
|
+
toolsUsed,
|
|
157
|
+
breakdown,
|
|
158
|
+
calculation: {
|
|
159
|
+
formula: formulaStr,
|
|
160
|
+
weights: calculationWeights,
|
|
161
|
+
normalized: formulaStr
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function getRating(score) {
|
|
166
|
+
if (score >= 90) return "Excellent";
|
|
167
|
+
if (score >= 75) return "Good";
|
|
168
|
+
if (score >= 60) return "Fair";
|
|
169
|
+
if (score >= 40) return "Needs Work";
|
|
170
|
+
return "Critical";
|
|
171
|
+
}
|
|
172
|
+
function getRatingWithContext(score, fileCount, modelTier = "standard") {
|
|
173
|
+
const threshold = getRecommendedThreshold(fileCount, modelTier);
|
|
174
|
+
const normalized = score - threshold + 70;
|
|
175
|
+
return getRating(normalized);
|
|
176
|
+
}
|
|
177
|
+
function getRatingDisplay(rating) {
|
|
178
|
+
switch (rating) {
|
|
179
|
+
case "Excellent":
|
|
180
|
+
return { emoji: "\u2705", color: "green" };
|
|
181
|
+
case "Good":
|
|
182
|
+
return { emoji: "\u{1F44D}", color: "blue" };
|
|
183
|
+
case "Fair":
|
|
184
|
+
return { emoji: "\u26A0\uFE0F", color: "yellow" };
|
|
185
|
+
case "Needs Work":
|
|
186
|
+
return { emoji: "\u{1F528}", color: "orange" };
|
|
187
|
+
case "Critical":
|
|
188
|
+
return { emoji: "\u274C", color: "red" };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function formatScore(result) {
|
|
192
|
+
const { emoji } = getRatingDisplay(result.rating);
|
|
193
|
+
return `${result.overall}/100 (${result.rating}) ${emoji}`;
|
|
194
|
+
}
|
|
195
|
+
function formatToolScore(output) {
|
|
196
|
+
let result = ` Score: ${output.score}/100
|
|
197
|
+
|
|
198
|
+
`;
|
|
199
|
+
if (output.factors && output.factors.length > 0) {
|
|
200
|
+
result += ` Factors:
|
|
201
|
+
`;
|
|
202
|
+
output.factors.forEach((factor) => {
|
|
203
|
+
const impactSign = factor.impact > 0 ? "+" : "";
|
|
204
|
+
result += ` \u2022 ${factor.name}: ${impactSign}${factor.impact} - ${factor.description}
|
|
205
|
+
`;
|
|
206
|
+
});
|
|
207
|
+
result += "\n";
|
|
208
|
+
}
|
|
209
|
+
if (output.recommendations && output.recommendations.length > 0) {
|
|
210
|
+
result += ` Recommendations:
|
|
211
|
+
`;
|
|
212
|
+
output.recommendations.forEach((rec, i) => {
|
|
213
|
+
const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
|
|
214
|
+
result += ` ${i + 1}. ${priorityIcon} ${rec.action}
|
|
215
|
+
`;
|
|
216
|
+
result += ` Impact: +${rec.estimatedImpact} points
|
|
217
|
+
|
|
218
|
+
`;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// src/utils/visualization.ts
|
|
225
|
+
function generateHTML(graph) {
|
|
226
|
+
const payload = JSON.stringify(graph, null, 2);
|
|
227
|
+
return `<!doctype html>
|
|
228
|
+
<html>
|
|
229
|
+
<head>
|
|
230
|
+
<meta charset="utf-8" />
|
|
231
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
232
|
+
<title>AIReady Visualization</title>
|
|
233
|
+
<style>
|
|
234
|
+
html,body { height: 100%; margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0 }
|
|
235
|
+
#container { display:flex; height:100vh }
|
|
236
|
+
#panel { width: 320px; padding: 16px; background: #071130; box-shadow: -2px 0 8px rgba(0,0,0,0.3); overflow:auto }
|
|
237
|
+
#canvasWrap { flex:1; display:flex; align-items:center; justify-content:center }
|
|
238
|
+
canvas { background: #0b1220; border-radius:8px }
|
|
239
|
+
.stat { margin-bottom:12px }
|
|
240
|
+
</style>
|
|
241
|
+
</head>
|
|
242
|
+
<body>
|
|
243
|
+
<div id="container">
|
|
244
|
+
<div id="canvasWrap"><canvas id="canvas" width="1200" height="800"></canvas></div>
|
|
245
|
+
<div id="panel">
|
|
246
|
+
<h2>AIReady Visualization</h2>
|
|
247
|
+
<div class="stat"><strong>Files:</strong> <span id="stat-files"></span></div>
|
|
248
|
+
<div class="stat"><strong>Dependencies:</strong> <span id="stat-deps"></span></div>
|
|
249
|
+
<div class="stat"><strong>Legend</strong></div>
|
|
250
|
+
<div style="font-size:13px;line-height:1.3;color:#cbd5e1;margin-top:8px">
|
|
251
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ff4d4f;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Critical</strong>: highest severity issues.</div>
|
|
252
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ff9900;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Major</strong>: important issues.</div>
|
|
253
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#ffd666;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Minor</strong>: low priority issues.</div>
|
|
254
|
+
<div style="margin-bottom:8px"><span style="display:inline-block;width:12px;height:12px;background:#91d5ff;margin-right:8px;border:1px solid rgba(255,255,255,0.06)"></span><strong>Info</strong>: informational notes.</div>
|
|
255
|
+
<div style="margin-top:10px;color:#94a3b8"><strong>Node size</strong>: larger = higher token cost, more issues or dependency weight.</div>
|
|
256
|
+
<div style="margin-top:6px;color:#94a3b8"><strong>Proximity</strong>: nodes that are spatially close are more contextually related; relatedness is represented by distance and size rather than explicit edges.</div>
|
|
257
|
+
<div style="margin-top:6px;color:#94a3b8"><strong>Edge colors</strong>: <span style="color:#fb7e81">Similarity</span>, <span style="color:#84c1ff">Dependency</span>, <span style="color:#ffa500">Reference</span>, default <span style="color:#334155">Other</span>.</div>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
|
|
262
|
+
<script>
|
|
263
|
+
const graphData = ${payload};
|
|
264
|
+
document.getElementById('stat-files').textContent = graphData.metadata.totalFiles;
|
|
265
|
+
document.getElementById('stat-deps').textContent = graphData.metadata.totalDependencies;
|
|
266
|
+
|
|
267
|
+
const canvas = document.getElementById('canvas');
|
|
268
|
+
const ctx = canvas.getContext('2d');
|
|
269
|
+
|
|
270
|
+
const nodes = graphData.nodes.map((n, i) => ({
|
|
271
|
+
...n,
|
|
272
|
+
x: canvas.width / 2 + Math.cos(i / graphData.nodes.length * Math.PI * 2) * (Math.min(canvas.width, canvas.height) / 3),
|
|
273
|
+
y: canvas.height / 2 + Math.sin(i / graphData.nodes.length * Math.PI * 2) * (Math.min(canvas.width, canvas.height) / 3),
|
|
274
|
+
}));
|
|
275
|
+
|
|
276
|
+
function draw() {
|
|
277
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
278
|
+
|
|
279
|
+
graphData.edges.forEach(edge => {
|
|
280
|
+
const s = nodes.find(n => n.id === edge.source);
|
|
281
|
+
const t = nodes.find(n => n.id === edge.target);
|
|
282
|
+
if (!s || !t) return;
|
|
283
|
+
if (edge.type === 'related') return;
|
|
284
|
+
if (edge.type === 'similarity') {
|
|
285
|
+
ctx.strokeStyle = '#fb7e81';
|
|
286
|
+
ctx.lineWidth = 1.2;
|
|
287
|
+
} else if (edge.type === 'dependency') {
|
|
288
|
+
ctx.strokeStyle = '#84c1ff';
|
|
289
|
+
ctx.lineWidth = 1.0;
|
|
290
|
+
} else if (edge.type === 'reference') {
|
|
291
|
+
ctx.strokeStyle = '#ffa500';
|
|
292
|
+
ctx.lineWidth = 0.9;
|
|
293
|
+
} else {
|
|
294
|
+
ctx.strokeStyle = '#334155';
|
|
295
|
+
ctx.lineWidth = 0.8;
|
|
296
|
+
}
|
|
297
|
+
ctx.beginPath();
|
|
298
|
+
ctx.moveTo(s.x, s.y);
|
|
299
|
+
ctx.lineTo(t.x, t.y);
|
|
300
|
+
ctx.stroke();
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
const groups = {};
|
|
304
|
+
nodes.forEach(n => {
|
|
305
|
+
const g = n.group || '__default';
|
|
306
|
+
if (!groups[g]) groups[g] = { minX: n.x, minY: n.y, maxX: n.x, maxY: n.y };
|
|
307
|
+
groups[g].minX = Math.min(groups[g].minX, n.x);
|
|
308
|
+
groups[g].minY = Math.min(groups[g].minY, n.y);
|
|
309
|
+
groups[g].maxX = Math.max(groups[g].maxX, n.x);
|
|
310
|
+
groups[g].maxY = Math.max(groups[g].maxY, n.y);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const groupRelations = {};
|
|
314
|
+
graphData.edges.forEach(edge => {
|
|
315
|
+
const sNode = nodes.find(n => n.id === edge.source);
|
|
316
|
+
const tNode = nodes.find(n => n.id === edge.target);
|
|
317
|
+
if (!sNode || !tNode) return;
|
|
318
|
+
const g1 = sNode.group || '__default';
|
|
319
|
+
const g2 = tNode.group || '__default';
|
|
320
|
+
if (g1 === g2) return;
|
|
321
|
+
const key = g1 < g2 ? g1 + '::' + g2 : g2 + '::' + g1;
|
|
322
|
+
groupRelations[key] = (groupRelations[key] || 0) + 1;
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
Object.keys(groupRelations).forEach(k => {
|
|
326
|
+
const count = groupRelations[k];
|
|
327
|
+
const [ga, gb] = k.split('::');
|
|
328
|
+
if (!groups[ga] || !groups[gb]) return;
|
|
329
|
+
const ax = (groups[ga].minX + groups[ga].maxX) / 2;
|
|
330
|
+
const ay = (groups[ga].minY + groups[ga].maxY) / 2;
|
|
331
|
+
const bx = (groups[gb].minX + groups[gb].maxX) / 2;
|
|
332
|
+
const by = (groups[gb].minY + groups[gb].maxY) / 2;
|
|
333
|
+
ctx.beginPath();
|
|
334
|
+
ctx.strokeStyle = 'rgba(148,163,184,0.25)';
|
|
335
|
+
ctx.lineWidth = Math.min(6, 0.6 + Math.sqrt(count));
|
|
336
|
+
ctx.moveTo(ax, ay);
|
|
337
|
+
ctx.lineTo(bx, by);
|
|
338
|
+
ctx.stroke();
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
Object.keys(groups).forEach(g => {
|
|
342
|
+
if (g === '__default') return;
|
|
343
|
+
const box = groups[g];
|
|
344
|
+
const pad = 16;
|
|
345
|
+
const x = box.minX - pad;
|
|
346
|
+
const y = box.minY - pad;
|
|
347
|
+
const w = (box.maxX - box.minX) + pad * 2;
|
|
348
|
+
const h = (box.maxY - box.minY) + pad * 2;
|
|
349
|
+
ctx.save();
|
|
350
|
+
ctx.fillStyle = 'rgba(30,64,175,0.04)';
|
|
351
|
+
ctx.strokeStyle = 'rgba(30,64,175,0.12)';
|
|
352
|
+
ctx.lineWidth = 1.2;
|
|
353
|
+
const r = 8;
|
|
354
|
+
ctx.beginPath();
|
|
355
|
+
ctx.moveTo(x + r, y);
|
|
356
|
+
ctx.arcTo(x + w, y, x + w, y + h, r);
|
|
357
|
+
ctx.arcTo(x + w, y + h, x, y + h, r);
|
|
358
|
+
ctx.arcTo(x, y + h, x, y, r);
|
|
359
|
+
ctx.arcTo(x, y, x + w, y, r);
|
|
360
|
+
ctx.closePath();
|
|
361
|
+
ctx.fill();
|
|
362
|
+
ctx.stroke();
|
|
363
|
+
ctx.restore();
|
|
364
|
+
ctx.fillStyle = '#94a3b8';
|
|
365
|
+
ctx.font = '11px sans-serif';
|
|
366
|
+
ctx.fillText(g, x + 8, y + 14);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
nodes.forEach(n => {
|
|
370
|
+
const sizeVal = (n.size || n.value || 1);
|
|
371
|
+
const r = 6 + (sizeVal / 2);
|
|
372
|
+
ctx.beginPath();
|
|
373
|
+
ctx.fillStyle = n.color || '#60a5fa';
|
|
374
|
+
ctx.arc(n.x, n.y, r, 0, Math.PI * 2);
|
|
375
|
+
ctx.fill();
|
|
376
|
+
|
|
377
|
+
ctx.fillStyle = '#e2e8f0';
|
|
378
|
+
ctx.font = '11px sans-serif';
|
|
379
|
+
ctx.textAlign = 'center';
|
|
380
|
+
ctx.fillText(n.label || n.id.split('/').slice(-1)[0], n.x, n.y + r + 12);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
draw();
|
|
385
|
+
</script>
|
|
386
|
+
</body>
|
|
387
|
+
</html>`;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export {
|
|
391
|
+
Language,
|
|
392
|
+
LANGUAGE_EXTENSIONS,
|
|
393
|
+
ParseError,
|
|
394
|
+
DEFAULT_TOOL_WEIGHTS,
|
|
395
|
+
TOOL_NAME_MAP,
|
|
396
|
+
CONTEXT_TIER_THRESHOLDS,
|
|
397
|
+
SIZE_ADJUSTED_THRESHOLDS,
|
|
398
|
+
getProjectSizeTier,
|
|
399
|
+
getRecommendedThreshold,
|
|
400
|
+
normalizeToolName,
|
|
401
|
+
getToolWeight,
|
|
402
|
+
parseWeightString,
|
|
403
|
+
calculateOverallScore,
|
|
404
|
+
getRating,
|
|
405
|
+
getRatingWithContext,
|
|
406
|
+
getRatingDisplay,
|
|
407
|
+
formatScore,
|
|
408
|
+
formatToolScore,
|
|
409
|
+
generateHTML
|
|
410
|
+
};
|
package/dist/client.js
CHANGED
|
@@ -167,7 +167,7 @@ function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
|
167
167
|
for (const [toolName] of toolOutputs.entries()) {
|
|
168
168
|
const cliWeight = cliWeights?.get(toolName);
|
|
169
169
|
const configWeight = config?.tools?.[toolName]?.scoreWeight;
|
|
170
|
-
const weight = cliWeight ?? configWeight ?? DEFAULT_TOOL_WEIGHTS[toolName] ??
|
|
170
|
+
const weight = cliWeight ?? configWeight ?? DEFAULT_TOOL_WEIGHTS[toolName] ?? 5;
|
|
171
171
|
weights.set(toolName, weight);
|
|
172
172
|
}
|
|
173
173
|
let weightedSum = 0;
|
|
@@ -176,7 +176,7 @@ function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
|
176
176
|
const toolsUsed = [];
|
|
177
177
|
const calculationWeights = {};
|
|
178
178
|
for (const [toolName, output] of toolOutputs.entries()) {
|
|
179
|
-
const weight = weights.get(toolName) ||
|
|
179
|
+
const weight = weights.get(toolName) || 5;
|
|
180
180
|
const weightedScore = output.score * weight;
|
|
181
181
|
weightedSum += weightedScore;
|
|
182
182
|
totalWeight += weight;
|
|
@@ -188,7 +188,7 @@ function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
|
188
188
|
const rating = getRating(overall);
|
|
189
189
|
const formulaParts = Array.from(toolOutputs.entries()).map(
|
|
190
190
|
([name, output]) => {
|
|
191
|
-
const w = weights.get(name) ||
|
|
191
|
+
const w = weights.get(name) || 5;
|
|
192
192
|
return `(${output.score} \xD7 ${w})`;
|
|
193
193
|
}
|
|
194
194
|
);
|
|
@@ -233,7 +233,7 @@ function getRatingDisplay(rating) {
|
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
function formatScore(result) {
|
|
236
|
-
const { emoji
|
|
236
|
+
const { emoji } = getRatingDisplay(result.rating);
|
|
237
237
|
return `${result.overall}/100 (${result.rating}) ${emoji}`;
|
|
238
238
|
}
|
|
239
239
|
function formatToolScore(output) {
|
package/dist/client.mjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -117,15 +117,15 @@ __export(index_exports, {
|
|
|
117
117
|
module.exports = __toCommonJS(index_exports);
|
|
118
118
|
|
|
119
119
|
// src/types/language.ts
|
|
120
|
-
var Language = /* @__PURE__ */ ((
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return
|
|
120
|
+
var Language = /* @__PURE__ */ ((Language2) => {
|
|
121
|
+
Language2["TypeScript"] = "typescript";
|
|
122
|
+
Language2["JavaScript"] = "javascript";
|
|
123
|
+
Language2["Python"] = "python";
|
|
124
|
+
Language2["Java"] = "java";
|
|
125
|
+
Language2["Go"] = "go";
|
|
126
|
+
Language2["Rust"] = "rust";
|
|
127
|
+
Language2["CSharp"] = "csharp";
|
|
128
|
+
return Language2;
|
|
129
129
|
})(Language || {});
|
|
130
130
|
var LANGUAGE_EXTENSIONS = {
|
|
131
131
|
".ts": "typescript" /* TypeScript */,
|
|
@@ -901,7 +901,7 @@ function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
|
901
901
|
for (const [toolName] of toolOutputs.entries()) {
|
|
902
902
|
const cliWeight = cliWeights?.get(toolName);
|
|
903
903
|
const configWeight = config?.tools?.[toolName]?.scoreWeight;
|
|
904
|
-
const weight = cliWeight ?? configWeight ?? DEFAULT_TOOL_WEIGHTS[toolName] ??
|
|
904
|
+
const weight = cliWeight ?? configWeight ?? DEFAULT_TOOL_WEIGHTS[toolName] ?? 5;
|
|
905
905
|
weights.set(toolName, weight);
|
|
906
906
|
}
|
|
907
907
|
let weightedSum = 0;
|
|
@@ -910,7 +910,7 @@ function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
|
910
910
|
const toolsUsed = [];
|
|
911
911
|
const calculationWeights = {};
|
|
912
912
|
for (const [toolName, output] of toolOutputs.entries()) {
|
|
913
|
-
const weight = weights.get(toolName) ||
|
|
913
|
+
const weight = weights.get(toolName) || 5;
|
|
914
914
|
const weightedScore = output.score * weight;
|
|
915
915
|
weightedSum += weightedScore;
|
|
916
916
|
totalWeight += weight;
|
|
@@ -922,7 +922,7 @@ function calculateOverallScore(toolOutputs, config, cliWeights) {
|
|
|
922
922
|
const rating = getRating(overall);
|
|
923
923
|
const formulaParts = Array.from(toolOutputs.entries()).map(
|
|
924
924
|
([name, output]) => {
|
|
925
|
-
const w = weights.get(name) ||
|
|
925
|
+
const w = weights.get(name) || 5;
|
|
926
926
|
return `(${output.score} \xD7 ${w})`;
|
|
927
927
|
}
|
|
928
928
|
);
|
|
@@ -967,7 +967,7 @@ function getRatingDisplay(rating) {
|
|
|
967
967
|
}
|
|
968
968
|
}
|
|
969
969
|
function formatScore(result) {
|
|
970
|
-
const { emoji
|
|
970
|
+
const { emoji } = getRatingDisplay(result.rating);
|
|
971
971
|
return `${result.overall}/100 (${result.rating}) ${emoji}`;
|
|
972
972
|
}
|
|
973
973
|
function formatToolScore(output) {
|
|
@@ -1100,7 +1100,10 @@ function calculateTokenBudget(params) {
|
|
|
1100
1100
|
const totalWaste = wastedTokens.duplication + wastedTokens.fragmentation + wastedTokens.chattiness;
|
|
1101
1101
|
const efficiencyRatio = Math.max(
|
|
1102
1102
|
0,
|
|
1103
|
-
Math.min(
|
|
1103
|
+
Math.min(
|
|
1104
|
+
1,
|
|
1105
|
+
(totalContextTokens - totalWaste) / Math.max(1, totalContextTokens)
|
|
1106
|
+
)
|
|
1104
1107
|
);
|
|
1105
1108
|
return {
|
|
1106
1109
|
totalContextTokens: Math.round(totalContextTokens),
|
|
@@ -1124,7 +1127,8 @@ function estimateCostFromBudget(budget, model, config = {}) {
|
|
|
1124
1127
|
const tokensPerDay = wastePerQuery * cfg.queriesPerDevPerDay;
|
|
1125
1128
|
const tokensPerMonth = tokensPerDay * cfg.daysPerMonth;
|
|
1126
1129
|
const totalWeight = cfg.developerCount;
|
|
1127
|
-
const
|
|
1130
|
+
const price = config.pricePer1KTokens ?? model.pricePer1KInputTokens;
|
|
1131
|
+
const baseCost = tokensPerMonth / 1e3 * price * totalWeight;
|
|
1128
1132
|
let confidence = 0.85;
|
|
1129
1133
|
if (model.contextTier === "frontier") confidence = 0.7;
|
|
1130
1134
|
const variance = 0.25;
|
|
@@ -2004,7 +2008,9 @@ var ParserFactory = class _ParserFactory {
|
|
|
2004
2008
|
registerParser(parser) {
|
|
2005
2009
|
this.parsers.set(parser.language, parser);
|
|
2006
2010
|
parser.extensions.forEach((ext) => {
|
|
2007
|
-
|
|
2011
|
+
const lang = LANGUAGE_EXTENSIONS[ext] || parser.language;
|
|
2012
|
+
this.extensionMap.set(ext, lang);
|
|
2013
|
+
this.parsers.set(lang, parser);
|
|
2008
2014
|
});
|
|
2009
2015
|
}
|
|
2010
2016
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
getToolWeight,
|
|
19
19
|
normalizeToolName,
|
|
20
20
|
parseWeightString
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-UQGI67WR.mjs";
|
|
22
22
|
|
|
23
23
|
// src/utils/file-scanner.ts
|
|
24
24
|
import { glob } from "glob";
|
|
@@ -615,7 +615,10 @@ function calculateTokenBudget(params) {
|
|
|
615
615
|
const totalWaste = wastedTokens.duplication + wastedTokens.fragmentation + wastedTokens.chattiness;
|
|
616
616
|
const efficiencyRatio = Math.max(
|
|
617
617
|
0,
|
|
618
|
-
Math.min(
|
|
618
|
+
Math.min(
|
|
619
|
+
1,
|
|
620
|
+
(totalContextTokens - totalWaste) / Math.max(1, totalContextTokens)
|
|
621
|
+
)
|
|
619
622
|
);
|
|
620
623
|
return {
|
|
621
624
|
totalContextTokens: Math.round(totalContextTokens),
|
|
@@ -639,7 +642,8 @@ function estimateCostFromBudget(budget, model, config = {}) {
|
|
|
639
642
|
const tokensPerDay = wastePerQuery * cfg.queriesPerDevPerDay;
|
|
640
643
|
const tokensPerMonth = tokensPerDay * cfg.daysPerMonth;
|
|
641
644
|
const totalWeight = cfg.developerCount;
|
|
642
|
-
const
|
|
645
|
+
const price = config.pricePer1KTokens ?? model.pricePer1KInputTokens;
|
|
646
|
+
const baseCost = tokensPerMonth / 1e3 * price * totalWeight;
|
|
643
647
|
let confidence = 0.85;
|
|
644
648
|
if (model.contextTier === "frontier") confidence = 0.7;
|
|
645
649
|
const variance = 0.25;
|
|
@@ -1519,7 +1523,9 @@ var ParserFactory = class _ParserFactory {
|
|
|
1519
1523
|
registerParser(parser) {
|
|
1520
1524
|
this.parsers.set(parser.language, parser);
|
|
1521
1525
|
parser.extensions.forEach((ext) => {
|
|
1522
|
-
|
|
1526
|
+
const lang = LANGUAGE_EXTENSIONS[ext] || parser.language;
|
|
1527
|
+
this.extensionMap.set(ext, lang);
|
|
1528
|
+
this.parsers.set(lang, parser);
|
|
1523
1529
|
});
|
|
1524
1530
|
}
|
|
1525
1531
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/core",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.38",
|
|
4
4
|
"description": "Shared utilities for AIReady analysis tools",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "tsup src/index.ts src/client.ts --format cjs,esm --dts",
|
|
55
55
|
"dev": "tsup src/index.ts src/client.ts --format cjs,esm --watch",
|
|
56
|
+
"test": "vitest run",
|
|
56
57
|
"lint": "eslint src",
|
|
57
58
|
"clean": "rm -rf dist",
|
|
58
59
|
"release": "pnpm build && pnpm publish --no-git-checks"
|