clawculator 2.1.0 → 2.1.1
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/htmlReport.js +20 -25
package/package.json
CHANGED
|
@@ -5,15 +5,15 @@ const path = require('path');
|
|
|
5
5
|
const os = require('os');
|
|
6
6
|
|
|
7
7
|
function severityColor(severity) {
|
|
8
|
-
return { critical: '#ef4444', high: '#f97316', medium: '#eab308',
|
|
8
|
+
return { critical: '#ef4444', high: '#f97316', medium: '#eab308', info: '#22c55e' }[severity] || '#6b7280';
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
function severityBg(severity) {
|
|
12
|
-
return { critical: '#fef2f2', high: '#fff7ed', medium: '#fefce8',
|
|
12
|
+
return { critical: '#fef2f2', high: '#fff7ed', medium: '#fefce8', info: '#f0fdf4' }[severity] || '#f9fafb';
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
function severityIcon(severity) {
|
|
16
|
-
return { critical: '🔴', high: '🟠', medium: '🟡',
|
|
16
|
+
return { critical: '🔴', high: '🟠', medium: '🟡', info: '✅' }[severity] || '⚪';
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
function relativeAge(ageMs) {
|
|
@@ -50,8 +50,7 @@ async function generateHTMLReport(analysis, outPath) {
|
|
|
50
50
|
</div>
|
|
51
51
|
<div style="font-weight:600; color:#111; margin-bottom:4px">${f.message}</div>
|
|
52
52
|
${f.detail ? `<div style="color:#555; font-size:14px; margin-bottom:6px; white-space:pre-line">${f.detail}</div>` : ''}
|
|
53
|
-
${f.
|
|
54
|
-
${f.command ? `<div style="background:#0f172a; color:#7dd3fc; font-family:monospace; font-size:12px; padding:8px 12px; border-radius:6px; margin-top:8px">${f.command}</div>` : ''}
|
|
53
|
+
${f.recommendation ? `<div style="color:#16a34a; font-size:14px; margin-top:8px">→ Fix: ${f.recommendation}</div>` : ''}
|
|
55
54
|
</div>
|
|
56
55
|
`).join('');
|
|
57
56
|
|
|
@@ -59,19 +58,19 @@ async function generateHTMLReport(analysis, outPath) {
|
|
|
59
58
|
.sort((a, b) => (b.inputTokens + b.outputTokens) - (a.inputTokens + a.outputTokens))
|
|
60
59
|
.slice(0, 20)
|
|
61
60
|
.map(s => {
|
|
62
|
-
const keyDisplay = s.key.length >
|
|
61
|
+
const keyDisplay = s.key.length > 12 ? s.key.slice(0, 8) + '…' : s.key;
|
|
63
62
|
const flag = s.isOrphaned ? ' ⚠️' : '';
|
|
64
63
|
const age = s.ageMs ? relativeAge(s.ageMs) : 'unknown';
|
|
65
64
|
const absDate = s.updatedAt ? new Date(s.updatedAt).toLocaleString() : '';
|
|
66
65
|
const daily = s.dailyCost ? `$${s.dailyCost.toFixed(4)}/day` : '—';
|
|
67
66
|
return `
|
|
68
|
-
<tr style="${s.isOrphaned ? 'background:#fff7ed
|
|
69
|
-
<td style="padding:8px 12px; font-family:monospace; font-size:13px
|
|
70
|
-
<td style="padding:8px 12px
|
|
71
|
-
<td style="padding:8px 12px; text-align:right
|
|
67
|
+
<tr style="${s.isOrphaned ? 'background:#fff7ed' : ''}">
|
|
68
|
+
<td style="padding:8px 12px; font-family:monospace; font-size:13px">${keyDisplay}${flag}</td>
|
|
69
|
+
<td style="padding:8px 12px">${s.modelLabel || s.model}</td>
|
|
70
|
+
<td style="padding:8px 12px; text-align:right">${(s.inputTokens + s.outputTokens).toLocaleString()}</td>
|
|
72
71
|
<td style="padding:8px 12px; text-align:right; color:${s.cost > 0.01 ? '#ef4444' : '#22c55e'}">$${s.cost.toFixed(6)}</td>
|
|
73
72
|
<td style="padding:8px 12px; text-align:right; color:#f59e0b">${daily}</td>
|
|
74
|
-
<td style="padding:8px 12px; color:#
|
|
73
|
+
<td style="padding:8px 12px; color:#6b7280; font-size:13px" title="${absDate}">${age}</td>
|
|
75
74
|
</tr>
|
|
76
75
|
`}).join('');
|
|
77
76
|
|
|
@@ -88,16 +87,14 @@ async function generateHTMLReport(analysis, outPath) {
|
|
|
88
87
|
.logo { font-size: 42px; font-weight: 900; letter-spacing: -2px; background: linear-gradient(90deg, #38bdf8, #818cf8); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
|
|
89
88
|
.tagline { color: #94a3b8; margin-top: 8px; font-size: 16px; }
|
|
90
89
|
.container { max-width: 1000px; margin: 0 auto; padding: 32px 24px; }
|
|
91
|
-
.cards { display:
|
|
92
|
-
.
|
|
93
|
-
.card { display: table-cell; background: #1e293b; border-radius: 12px; padding: 20px; border: 1px solid #334155; width: 16.6%; }
|
|
90
|
+
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; margin-bottom: 32px; }
|
|
91
|
+
.card { background: #1e293b; border-radius: 12px; padding: 20px; border: 1px solid #334155; }
|
|
94
92
|
.card-value { font-size: 32px; font-weight: 800; }
|
|
95
93
|
.card-label { font-size: 13px; color: #94a3b8; margin-top: 4px; }
|
|
96
94
|
.section { background: #1e293b; border-radius: 12px; padding: 24px; margin-bottom: 24px; border: 1px solid #334155; }
|
|
97
95
|
.section-title { font-size: 18px; font-weight: 700; margin-bottom: 16px; color: #f1f5f9; }
|
|
98
96
|
table { width: 100%; border-collapse: collapse; }
|
|
99
|
-
th { background: #0f172a; padding: 10px 12px; text-align: left; font-size: 13px; color: #
|
|
100
|
-
td { color: #e2e8f0; }
|
|
97
|
+
th { background: #0f172a; padding: 10px 12px; text-align: left; font-size: 13px; color: #94a3b8; }
|
|
101
98
|
tr:nth-child(even) { background: #0f172a33; }
|
|
102
99
|
.footer { text-align: center; color: #475569; font-size: 13px; padding: 32px; }
|
|
103
100
|
.bleed { background: linear-gradient(135deg, #7f1d1d, #991b1b); border-radius: 12px; padding: 20px 24px; margin-bottom: 24px; border: 1px solid #ef4444; }
|
|
@@ -122,7 +119,7 @@ async function generateHTMLReport(analysis, outPath) {
|
|
|
122
119
|
<div style="color:#86efac; font-size:18px; font-weight:700">✅ No significant cost bleed detected</div>
|
|
123
120
|
</div>`}
|
|
124
121
|
|
|
125
|
-
<div class="cards"
|
|
122
|
+
<div class="cards">
|
|
126
123
|
<div class="card">
|
|
127
124
|
<div class="card-value" style="color:#ef4444">${summary.critical}</div>
|
|
128
125
|
<div class="card-label">🔴 Critical</div>
|
|
@@ -135,10 +132,6 @@ async function generateHTMLReport(analysis, outPath) {
|
|
|
135
132
|
<div class="card-value" style="color:#eab308">${summary.medium}</div>
|
|
136
133
|
<div class="card-label">🟡 Medium</div>
|
|
137
134
|
</div>
|
|
138
|
-
<div class="card">
|
|
139
|
-
<div class="card-value" style="color:#38bdf8">${summary.low || 0}</div>
|
|
140
|
-
<div class="card-label">🔵 Low</div>
|
|
141
|
-
</div>
|
|
142
135
|
<div class="card">
|
|
143
136
|
<div class="card-value" style="color:#22c55e">${summary.info}</div>
|
|
144
137
|
<div class="card-label">✅ OK</div>
|
|
@@ -151,7 +144,7 @@ async function generateHTMLReport(analysis, outPath) {
|
|
|
151
144
|
<div class="card-value" style="color:#818cf8">${(summary.totalTokensFound || 0).toLocaleString()}</div>
|
|
152
145
|
<div class="card-label">Total Tokens Found</div>
|
|
153
146
|
</div>
|
|
154
|
-
</div
|
|
147
|
+
</div>
|
|
155
148
|
|
|
156
149
|
<div class="section">
|
|
157
150
|
<div class="section-title">Findings</div>
|
|
@@ -178,9 +171,11 @@ async function generateHTMLReport(analysis, outPath) {
|
|
|
178
171
|
</body>
|
|
179
172
|
</html>`;
|
|
180
173
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
174
|
+
if (!outPath) {
|
|
175
|
+
outPath = path.join(os.tmpdir(), `clawculator-report-${Date.now()}.html`);
|
|
176
|
+
}
|
|
177
|
+
fs.writeFileSync(outPath, html, 'utf8');
|
|
178
|
+
return outPath;
|
|
184
179
|
}
|
|
185
180
|
|
|
186
181
|
module.exports = { generateHTMLReport };
|