clawculator 2.8.2 → 2.8.4
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/package.json +1 -1
- package/skills/clawculator/snapshotCard.js +59 -17
- package/src/snapshotCard.js +59 -17
package/package.json
CHANGED
|
@@ -17,18 +17,27 @@ function generateSnapshotCard(analysis, outputDir) {
|
|
|
17
17
|
const mediums = s.medium || 0;
|
|
18
18
|
const totalFindings = criticals + highs + mediums;
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
// ── Filter findings by type ────────────────────────────
|
|
21
|
+
// For the grade, only count CONFIG findings (things a new user would inherit)
|
|
22
|
+
// Exclude: historical session costs, untracked sessions, cache totals, cost gaps
|
|
23
|
+
// These are noise for "what does it cost to run this setup?"
|
|
24
|
+
const configFindings = (analysis.findings || []).filter(f => {
|
|
25
|
+
const t = (f.title || f.message || '').toLowerCase();
|
|
26
|
+
const src = (f.source || '').toLowerCase();
|
|
27
|
+
// Skip historical/session findings
|
|
28
|
+
if (t.includes('orphaned session')) return false;
|
|
29
|
+
if (t.includes('untracked session')) return false;
|
|
30
|
+
if (t.includes('prompt caching added')) return false;
|
|
31
|
+
if (t.includes('real cost') && t.includes('higher than')) return false;
|
|
32
|
+
if (t.includes('>50k tokens')) return false;
|
|
33
|
+
if (t.includes('pricing table')) return false;
|
|
34
|
+
// Keep config findings (heartbeat, whatsapp, hooks, crons, models, vision, memory)
|
|
35
|
+
return true;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const cfgCriticals = configFindings.filter(f => f.severity === 'critical').length;
|
|
39
|
+
const cfgHighs = configFindings.filter(f => f.severity === 'high').length;
|
|
40
|
+
const cfgMediums = configFindings.filter(f => f.severity === 'medium').length;
|
|
32
41
|
|
|
33
42
|
// ── Cost range (bucketed, not exact) ───────────────────
|
|
34
43
|
const todayCost = s.todayCost || 0;
|
|
@@ -42,6 +51,38 @@ function generateSnapshotCard(analysis, outputDir) {
|
|
|
42
51
|
else if (todayCost < 50) { costRange = '$25–50/day'; costEmoji = '🔥'; }
|
|
43
52
|
else { costRange = '$50+/day'; costEmoji = '🚨'; }
|
|
44
53
|
|
|
54
|
+
// ── Compute grade ──────────────────────────────────────
|
|
55
|
+
// Grade = "how well is this SETUP configured for cost efficiency?"
|
|
56
|
+
// Only counts config findings, not historical session data
|
|
57
|
+
let grade, gradeColor, gradeGlow, gradeEmoji;
|
|
58
|
+
|
|
59
|
+
let score = (cfgCriticals * 5) + (cfgHighs * 2) + (cfgMediums * 0.5);
|
|
60
|
+
|
|
61
|
+
// Cost bonus: low daily spend is the whole point
|
|
62
|
+
if (todayCost < 1) score -= 4;
|
|
63
|
+
else if (todayCost < 5) score -= 3;
|
|
64
|
+
else if (todayCost < 10) score -= 1;
|
|
65
|
+
else if (todayCost > 50) score += 3;
|
|
66
|
+
|
|
67
|
+
// No criticals bonus
|
|
68
|
+
if (cfgCriticals === 0) score -= 2;
|
|
69
|
+
|
|
70
|
+
if (score < 0) score = 0;
|
|
71
|
+
|
|
72
|
+
if (score === 0) {
|
|
73
|
+
grade = 'A+'; gradeColor = '#22c55e'; gradeGlow = 'rgba(34,197,94,0.3)'; gradeEmoji = '🏆';
|
|
74
|
+
} else if (score <= 2) {
|
|
75
|
+
grade = 'A'; gradeColor = '#22c55e'; gradeGlow = 'rgba(34,197,94,0.2)'; gradeEmoji = '✅';
|
|
76
|
+
} else if (score <= 5) {
|
|
77
|
+
grade = 'B+'; gradeColor = '#84cc16'; gradeGlow = 'rgba(132,204,22,0.2)'; gradeEmoji = '👍';
|
|
78
|
+
} else if (score <= 8) {
|
|
79
|
+
grade = 'B'; gradeColor = '#f59e0b'; gradeGlow = 'rgba(245,158,11,0.2)'; gradeEmoji = '👍';
|
|
80
|
+
} else if (score <= 12) {
|
|
81
|
+
grade = 'C'; gradeColor = '#f97316'; gradeGlow = 'rgba(249,115,22,0.2)'; gradeEmoji = '⚠️';
|
|
82
|
+
} else {
|
|
83
|
+
grade = 'D'; gradeColor = '#ef4444'; gradeGlow = 'rgba(239,68,68,0.2)'; gradeEmoji = '🔥';
|
|
84
|
+
}
|
|
85
|
+
|
|
45
86
|
// ── Setup complexity from config ───────────────────────
|
|
46
87
|
const config = analysis.config || {};
|
|
47
88
|
|
|
@@ -66,7 +107,8 @@ function generateSnapshotCard(analysis, outputDir) {
|
|
|
66
107
|
const modelCount = modelSet.size || 1;
|
|
67
108
|
|
|
68
109
|
const totalTokens = s.totalTokensFound || 1;
|
|
69
|
-
const
|
|
110
|
+
const totalWithCache = totalTokens + (s.totalCacheRead || 0) + (s.totalCacheWrite || 0);
|
|
111
|
+
const cacheEfficiency = Math.min(99, Math.round((s.totalCacheRead || 0) / totalWithCache * 100));
|
|
70
112
|
|
|
71
113
|
// ── Build stat pills ──────────────────────────────────
|
|
72
114
|
const pills = [];
|
|
@@ -79,11 +121,11 @@ function generateSnapshotCard(analysis, outputDir) {
|
|
|
79
121
|
pills.push({ icon: '🧠', label: `${modelCount} model${modelCount>1?'s':''}` });
|
|
80
122
|
if (cacheEfficiency > 0) pills.push({ icon: '⚡', label: `${cacheEfficiency}% cache` });
|
|
81
123
|
|
|
82
|
-
// ── Findings summary
|
|
124
|
+
// ── Findings summary (config only) ─────────────────────
|
|
83
125
|
const findingSummary = [];
|
|
84
|
-
if (
|
|
85
|
-
if (
|
|
86
|
-
if (
|
|
126
|
+
if (cfgCriticals > 0) findingSummary.push(`🔴 ${cfgCriticals} critical`);
|
|
127
|
+
if (cfgHighs > 0) findingSummary.push(`🟠 ${cfgHighs} high`);
|
|
128
|
+
if (cfgMediums > 0) findingSummary.push(`🟡 ${cfgMediums} medium`);
|
|
87
129
|
|
|
88
130
|
const html = `<!DOCTYPE html>
|
|
89
131
|
<html lang="en">
|
package/src/snapshotCard.js
CHANGED
|
@@ -17,18 +17,27 @@ function generateSnapshotCard(analysis, outputDir) {
|
|
|
17
17
|
const mediums = s.medium || 0;
|
|
18
18
|
const totalFindings = criticals + highs + mediums;
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
// ── Filter findings by type ────────────────────────────
|
|
21
|
+
// For the grade, only count CONFIG findings (things a new user would inherit)
|
|
22
|
+
// Exclude: historical session costs, untracked sessions, cache totals, cost gaps
|
|
23
|
+
// These are noise for "what does it cost to run this setup?"
|
|
24
|
+
const configFindings = (analysis.findings || []).filter(f => {
|
|
25
|
+
const t = (f.title || f.message || '').toLowerCase();
|
|
26
|
+
const src = (f.source || '').toLowerCase();
|
|
27
|
+
// Skip historical/session findings
|
|
28
|
+
if (t.includes('orphaned session')) return false;
|
|
29
|
+
if (t.includes('untracked session')) return false;
|
|
30
|
+
if (t.includes('prompt caching added')) return false;
|
|
31
|
+
if (t.includes('real cost') && t.includes('higher than')) return false;
|
|
32
|
+
if (t.includes('>50k tokens')) return false;
|
|
33
|
+
if (t.includes('pricing table')) return false;
|
|
34
|
+
// Keep config findings (heartbeat, whatsapp, hooks, crons, models, vision, memory)
|
|
35
|
+
return true;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const cfgCriticals = configFindings.filter(f => f.severity === 'critical').length;
|
|
39
|
+
const cfgHighs = configFindings.filter(f => f.severity === 'high').length;
|
|
40
|
+
const cfgMediums = configFindings.filter(f => f.severity === 'medium').length;
|
|
32
41
|
|
|
33
42
|
// ── Cost range (bucketed, not exact) ───────────────────
|
|
34
43
|
const todayCost = s.todayCost || 0;
|
|
@@ -42,6 +51,38 @@ function generateSnapshotCard(analysis, outputDir) {
|
|
|
42
51
|
else if (todayCost < 50) { costRange = '$25–50/day'; costEmoji = '🔥'; }
|
|
43
52
|
else { costRange = '$50+/day'; costEmoji = '🚨'; }
|
|
44
53
|
|
|
54
|
+
// ── Compute grade ──────────────────────────────────────
|
|
55
|
+
// Grade = "how well is this SETUP configured for cost efficiency?"
|
|
56
|
+
// Only counts config findings, not historical session data
|
|
57
|
+
let grade, gradeColor, gradeGlow, gradeEmoji;
|
|
58
|
+
|
|
59
|
+
let score = (cfgCriticals * 5) + (cfgHighs * 2) + (cfgMediums * 0.5);
|
|
60
|
+
|
|
61
|
+
// Cost bonus: low daily spend is the whole point
|
|
62
|
+
if (todayCost < 1) score -= 4;
|
|
63
|
+
else if (todayCost < 5) score -= 3;
|
|
64
|
+
else if (todayCost < 10) score -= 1;
|
|
65
|
+
else if (todayCost > 50) score += 3;
|
|
66
|
+
|
|
67
|
+
// No criticals bonus
|
|
68
|
+
if (cfgCriticals === 0) score -= 2;
|
|
69
|
+
|
|
70
|
+
if (score < 0) score = 0;
|
|
71
|
+
|
|
72
|
+
if (score === 0) {
|
|
73
|
+
grade = 'A+'; gradeColor = '#22c55e'; gradeGlow = 'rgba(34,197,94,0.3)'; gradeEmoji = '🏆';
|
|
74
|
+
} else if (score <= 2) {
|
|
75
|
+
grade = 'A'; gradeColor = '#22c55e'; gradeGlow = 'rgba(34,197,94,0.2)'; gradeEmoji = '✅';
|
|
76
|
+
} else if (score <= 5) {
|
|
77
|
+
grade = 'B+'; gradeColor = '#84cc16'; gradeGlow = 'rgba(132,204,22,0.2)'; gradeEmoji = '👍';
|
|
78
|
+
} else if (score <= 8) {
|
|
79
|
+
grade = 'B'; gradeColor = '#f59e0b'; gradeGlow = 'rgba(245,158,11,0.2)'; gradeEmoji = '👍';
|
|
80
|
+
} else if (score <= 12) {
|
|
81
|
+
grade = 'C'; gradeColor = '#f97316'; gradeGlow = 'rgba(249,115,22,0.2)'; gradeEmoji = '⚠️';
|
|
82
|
+
} else {
|
|
83
|
+
grade = 'D'; gradeColor = '#ef4444'; gradeGlow = 'rgba(239,68,68,0.2)'; gradeEmoji = '🔥';
|
|
84
|
+
}
|
|
85
|
+
|
|
45
86
|
// ── Setup complexity from config ───────────────────────
|
|
46
87
|
const config = analysis.config || {};
|
|
47
88
|
|
|
@@ -66,7 +107,8 @@ function generateSnapshotCard(analysis, outputDir) {
|
|
|
66
107
|
const modelCount = modelSet.size || 1;
|
|
67
108
|
|
|
68
109
|
const totalTokens = s.totalTokensFound || 1;
|
|
69
|
-
const
|
|
110
|
+
const totalWithCache = totalTokens + (s.totalCacheRead || 0) + (s.totalCacheWrite || 0);
|
|
111
|
+
const cacheEfficiency = Math.min(99, Math.round((s.totalCacheRead || 0) / totalWithCache * 100));
|
|
70
112
|
|
|
71
113
|
// ── Build stat pills ──────────────────────────────────
|
|
72
114
|
const pills = [];
|
|
@@ -79,11 +121,11 @@ function generateSnapshotCard(analysis, outputDir) {
|
|
|
79
121
|
pills.push({ icon: '🧠', label: `${modelCount} model${modelCount>1?'s':''}` });
|
|
80
122
|
if (cacheEfficiency > 0) pills.push({ icon: '⚡', label: `${cacheEfficiency}% cache` });
|
|
81
123
|
|
|
82
|
-
// ── Findings summary
|
|
124
|
+
// ── Findings summary (config only) ─────────────────────
|
|
83
125
|
const findingSummary = [];
|
|
84
|
-
if (
|
|
85
|
-
if (
|
|
86
|
-
if (
|
|
126
|
+
if (cfgCriticals > 0) findingSummary.push(`🔴 ${cfgCriticals} critical`);
|
|
127
|
+
if (cfgHighs > 0) findingSummary.push(`🟠 ${cfgHighs} high`);
|
|
128
|
+
if (cfgMediums > 0) findingSummary.push(`🟡 ${cfgMediums} medium`);
|
|
87
129
|
|
|
88
130
|
const html = `<!DOCTYPE html>
|
|
89
131
|
<html lang="en">
|