@roastcodes/ttdash 6.1.5 → 6.1.6
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/README.md +14 -4
- package/dist/assets/AutoImportModal-Dqbl8H04.js +2 -0
- package/dist/assets/CustomTooltip-DBPq6A_5.js +1 -0
- package/dist/assets/DrillDownModal-BKuxN4GY.js +1 -0
- package/dist/assets/index-D8uaHhGW.js +4 -0
- package/dist/index.html +3 -3
- package/package.json +18 -5
- package/server/model-normalization.json +28 -0
- package/server/report/charts.js +127 -54
- package/server/report/index.js +25 -5
- package/server/report/utils.js +292 -86
- package/server.js +302 -188
- package/src/locales/de/common.json +14 -0
- package/src/locales/en/common.json +14 -0
- package/usage-normalizer.js +44 -36
- package/dist/assets/AutoImportModal-Dig6ASar.js +0 -2
- package/dist/assets/CustomTooltip-Be-rHcDB.js +0 -1
- package/dist/assets/DrillDownModal-DXP44-00.js +0 -1
- package/dist/assets/index-_318nw_j.js +0 -4
package/dist/index.html
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="de" class="dark">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<link rel="icon" type="image/png" sizes="256x256" href="/favicon.png" />
|
|
9
9
|
<link rel="shortcut icon" href="/favicon.png" />
|
|
10
10
|
<link rel="apple-touch-icon" href="/favicon.png" />
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-D8uaHhGW.js"></script>
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-COnpUsM8.js">
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/charts-vendor-CiBqdKXh.js">
|
|
14
14
|
<link rel="modulepreload" crossorigin href="/assets/react-vendor-0R1rd57Z.js">
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<link rel="modulepreload" crossorigin href="/assets/icons-vendor-DFoaijFJ.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="/assets/dialog-Cn1m7WhC.js">
|
|
19
19
|
<link rel="modulepreload" crossorigin href="/assets/button-D7Ib8H7t.js">
|
|
20
|
-
<link rel="modulepreload" crossorigin href="/assets/CustomTooltip-
|
|
20
|
+
<link rel="modulepreload" crossorigin href="/assets/CustomTooltip-DBPq6A_5.js">
|
|
21
21
|
<link rel="stylesheet" crossorigin href="/assets/index-TppJ6Iqj.css">
|
|
22
22
|
</head>
|
|
23
23
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roastcodes/ttdash",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.6",
|
|
4
4
|
"description": "Local-first dashboard and CLI for toktrack usage data",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"repository": {
|
|
@@ -16,7 +16,12 @@
|
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
18
|
"dev": "vite",
|
|
19
|
-
"build": "vite build",
|
|
19
|
+
"build:app": "vite build",
|
|
20
|
+
"build": "npm run format:check && npm run lint && npm run build:app",
|
|
21
|
+
"format": "prettier . --write",
|
|
22
|
+
"format:check": "prettier . --check",
|
|
23
|
+
"lint": "eslint .",
|
|
24
|
+
"lint:fix": "eslint . --fix",
|
|
20
25
|
"preview": "vite preview",
|
|
21
26
|
"start": "node server.js",
|
|
22
27
|
"start:test-server": "node scripts/start-test-server.js",
|
|
@@ -24,14 +29,15 @@
|
|
|
24
29
|
"test:unit": "vitest run",
|
|
25
30
|
"test:unit:watch": "vitest",
|
|
26
31
|
"test:unit:coverage": "vitest run --coverage",
|
|
27
|
-
"test:e2e": "npm run build && playwright test",
|
|
32
|
+
"test:e2e": "npm run build:app && playwright test",
|
|
28
33
|
"test:e2e:ci": "playwright test",
|
|
29
34
|
"test:all": "npm run test:unit && npm run test:e2e",
|
|
30
35
|
"pack:dry-run": "npm pack --dry-run",
|
|
36
|
+
"verify": "npm run format:check && npm run lint && tsc --noEmit && npm run test:unit && npm run build:app && npm run verify:package",
|
|
31
37
|
"verify:package": "node scripts/verify-package.js",
|
|
32
38
|
"verify:registry-install": "node scripts/verify-registry-install.js",
|
|
33
|
-
"verify:release": "npm run test:unit:coverage && npm run build && npm run verify:package",
|
|
34
|
-
"prepare": "npm run build"
|
|
39
|
+
"verify:release": "npm run format:check && npm run lint && tsc --noEmit && npm run test:unit:coverage && npm run build:app && npm run verify:package",
|
|
40
|
+
"prepare": "npm run build:app"
|
|
35
41
|
},
|
|
36
42
|
"files": [
|
|
37
43
|
"server.js",
|
|
@@ -59,6 +65,7 @@
|
|
|
59
65
|
"node": ">=20"
|
|
60
66
|
},
|
|
61
67
|
"devDependencies": {
|
|
68
|
+
"@eslint/js": "^9.39.4",
|
|
62
69
|
"@playwright/test": "^1.59.1",
|
|
63
70
|
"@radix-ui/react-dialog": "^1.1.14",
|
|
64
71
|
"@radix-ui/react-select": "^2.2.2",
|
|
@@ -76,15 +83,21 @@
|
|
|
76
83
|
"class-variance-authority": "^0.7.1",
|
|
77
84
|
"clsx": "^2.1.1",
|
|
78
85
|
"cmdk": "^1.1.1",
|
|
86
|
+
"eslint": "^9.39.4",
|
|
87
|
+
"eslint-config-prettier": "^10.1.8",
|
|
88
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
79
89
|
"framer-motion": "^12.6.5",
|
|
90
|
+
"globals": "^17.5.0",
|
|
80
91
|
"jsdom": "^29.0.2",
|
|
81
92
|
"lucide-react": "^1.7.0",
|
|
93
|
+
"prettier": "^3.8.2",
|
|
82
94
|
"react": "^19.2.4",
|
|
83
95
|
"react-dom": "^19.2.4",
|
|
84
96
|
"recharts": "^3.8.1",
|
|
85
97
|
"tailwind-merge": "^3.0.2",
|
|
86
98
|
"tailwindcss": "^4.1.3",
|
|
87
99
|
"typescript": "^6.0.2",
|
|
100
|
+
"typescript-eslint": "^8.58.1",
|
|
88
101
|
"vite": "^8.0.8",
|
|
89
102
|
"vitest": "^4.1.3"
|
|
90
103
|
},
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"displayAliases": [
|
|
3
|
+
{ "pattern": "(^|-)gpt-5-4$", "name": "GPT-5.4" },
|
|
4
|
+
{ "pattern": "(^|-)gpt-5$", "name": "GPT-5" },
|
|
5
|
+
{ "pattern": "(^|-)opus-4-6$", "name": "Opus 4.6" },
|
|
6
|
+
{ "pattern": "(^|-)opus-4-5$", "name": "Opus 4.5" },
|
|
7
|
+
{ "pattern": "(^|-)sonnet-4-6$", "name": "Sonnet 4.6" },
|
|
8
|
+
{ "pattern": "(^|-)sonnet-4-5$", "name": "Sonnet 4.5" },
|
|
9
|
+
{ "pattern": "(^|-)haiku-4-5$", "name": "Haiku 4.5" },
|
|
10
|
+
{ "pattern": "(^|-)gemini-3-flash-preview$", "name": "Gemini 3 Flash Preview" },
|
|
11
|
+
{ "pattern": "(^|-)opencode$", "name": "OpenCode" }
|
|
12
|
+
],
|
|
13
|
+
"providerMatchers": [
|
|
14
|
+
{ "pattern": "(^|-)opencode($|-)", "provider": "OpenCode" },
|
|
15
|
+
{
|
|
16
|
+
"pattern": "openai-codex|(^|-)codex($|-)|(^|-)gpt($|-)|(^|[^a-z0-9])o\\d(?:$|[^a-z0-9])|openai",
|
|
17
|
+
"provider": "OpenAI"
|
|
18
|
+
},
|
|
19
|
+
{ "pattern": "claude|anthropic|opus|sonnet|haiku", "provider": "Anthropic" },
|
|
20
|
+
{ "pattern": "gemini|google|vertex", "provider": "Google" },
|
|
21
|
+
{ "pattern": "grok|xai", "provider": "xAI" },
|
|
22
|
+
{ "pattern": "llama|meta-llama|meta/", "provider": "Meta" },
|
|
23
|
+
{ "pattern": "command|cohere", "provider": "Cohere" },
|
|
24
|
+
{ "pattern": "mistral", "provider": "Mistral" },
|
|
25
|
+
{ "pattern": "deepseek", "provider": "DeepSeek" },
|
|
26
|
+
{ "pattern": "qwen|alibaba", "provider": "Alibaba" }
|
|
27
|
+
]
|
|
28
|
+
}
|
package/server/report/charts.js
CHANGED
|
@@ -25,7 +25,18 @@ function truncateSvgLabel(value, maxLength = 28) {
|
|
|
25
25
|
return `${stringValue.slice(0, Math.max(1, maxLength - 1)).trimEnd()}…`;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
function lineChart(
|
|
28
|
+
function lineChart(
|
|
29
|
+
data,
|
|
30
|
+
{
|
|
31
|
+
valueKey,
|
|
32
|
+
secondaryKey,
|
|
33
|
+
title,
|
|
34
|
+
stroke = '#1f6feb',
|
|
35
|
+
fill = 'rgba(31, 111, 235, 0.14)',
|
|
36
|
+
formatter = (value) => String(value),
|
|
37
|
+
fontFamily = DEFAULT_FONT_FAMILY,
|
|
38
|
+
},
|
|
39
|
+
) {
|
|
29
40
|
const width = 980;
|
|
30
41
|
const height = 360;
|
|
31
42
|
const margin = { top: 42, right: 28, bottom: 54, left: 74 };
|
|
@@ -39,16 +50,18 @@ function lineChart(data, { valueKey, secondaryKey, title, stroke = '#1f6feb', fi
|
|
|
39
50
|
const y = (value) => margin.top + plotHeight - (value / maxValue) * plotHeight;
|
|
40
51
|
|
|
41
52
|
const linePoints = values.map((value, index) => `${x(index)},${y(value)}`).join(' ');
|
|
42
|
-
const areaPoints =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
const areaPoints =
|
|
54
|
+
data.length > 1
|
|
55
|
+
? [
|
|
56
|
+
`${margin.left},${margin.top + plotHeight}`,
|
|
57
|
+
...values.map((value, index) => `${x(index)},${y(value)}`),
|
|
58
|
+
`${margin.left + plotWidth},${margin.top + plotHeight}`,
|
|
59
|
+
].join(' ')
|
|
60
|
+
: '';
|
|
61
|
+
const secondaryPoints =
|
|
62
|
+
secondaryValues.length > 0
|
|
63
|
+
? secondaryValues.map((value, index) => `${x(index)},${y(value)}`).join(' ')
|
|
64
|
+
: '';
|
|
52
65
|
const tickCount = 4;
|
|
53
66
|
const yTicks = Array.from({ length: tickCount + 1 }, (_, index) => {
|
|
54
67
|
const value = (maxValue / tickCount) * index;
|
|
@@ -59,33 +72,66 @@ function lineChart(data, { valueKey, secondaryKey, title, stroke = '#1f6feb', fi
|
|
|
59
72
|
});
|
|
60
73
|
const labelStep = Math.max(1, Math.ceil(data.length / 6));
|
|
61
74
|
|
|
62
|
-
return svgDoc(
|
|
75
|
+
return svgDoc(
|
|
76
|
+
width,
|
|
77
|
+
height,
|
|
78
|
+
`
|
|
63
79
|
<rect width="${width}" height="${height}" rx="24" fill="#ffffff"/>
|
|
64
80
|
<text x="${margin.left}" y="26" font-size="18" font-family="${fontFamily}" font-weight="700" fill="#122033">${escapeXml(title)}</text>
|
|
65
|
-
${yTicks
|
|
81
|
+
${yTicks
|
|
82
|
+
.map(
|
|
83
|
+
(tick) => `
|
|
66
84
|
<line x1="${margin.left}" y1="${tick.y}" x2="${margin.left + plotWidth}" y2="${tick.y}" stroke="#e6edf5" stroke-width="1"/>
|
|
67
85
|
<text x="${margin.left - 12}" y="${tick.y + 4}" text-anchor="end" font-size="11" font-family="${fontFamily}" fill="#5c6b7e">${escapeXml(formatter(tick.value))}</text>
|
|
68
|
-
|
|
86
|
+
`,
|
|
87
|
+
)
|
|
88
|
+
.join('')}
|
|
69
89
|
<line x1="${margin.left}" y1="${margin.top}" x2="${margin.left}" y2="${margin.top + plotHeight}" stroke="#98a6b7" stroke-width="1.2"/>
|
|
70
90
|
<line x1="${margin.left}" y1="${margin.top + plotHeight}" x2="${margin.left + plotWidth}" y2="${margin.top + plotHeight}" stroke="#98a6b7" stroke-width="1.2"/>
|
|
71
91
|
${areaPoints ? `<polygon points="${areaPoints}" fill="${fill}"/>` : ''}
|
|
72
92
|
${secondaryPoints ? `<polyline points="${secondaryPoints}" stroke="#f59e0b" stroke-width="2.5" stroke-dasharray="8 6" stroke-linecap="round" stroke-linejoin="round"/>` : ''}
|
|
73
|
-
${
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
${
|
|
94
|
+
data.length > 1
|
|
95
|
+
? `<polyline points="${linePoints}" stroke="${stroke}" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"/>`
|
|
96
|
+
: `<line x1="${x(0)}" y1="${margin.top + plotHeight}" x2="${x(0)}" y2="${y(values[0])}" stroke="${stroke}" stroke-width="3.5" stroke-linecap="round"/>`
|
|
97
|
+
}
|
|
98
|
+
${values
|
|
99
|
+
.map(
|
|
100
|
+
(value, index) => `
|
|
77
101
|
<circle cx="${x(index)}" cy="${y(value)}" r="${data.length > 40 ? 0 : 3.8}" fill="${stroke}"/>
|
|
78
|
-
|
|
79
|
-
|
|
102
|
+
`,
|
|
103
|
+
)
|
|
104
|
+
.join('')}
|
|
105
|
+
${data
|
|
106
|
+
.map((entry, index) =>
|
|
107
|
+
index % labelStep === 0 || index === data.length - 1
|
|
108
|
+
? `
|
|
80
109
|
<text x="${x(index)}" y="${height - 18}" text-anchor="middle" font-size="11" font-family="${fontFamily}" fill="#5c6b7e">${escapeXml(entry.label)}</text>
|
|
81
|
-
`
|
|
82
|
-
|
|
110
|
+
`
|
|
111
|
+
: '',
|
|
112
|
+
)
|
|
113
|
+
.join('')}
|
|
114
|
+
`,
|
|
115
|
+
);
|
|
83
116
|
}
|
|
84
117
|
|
|
85
|
-
function horizontalBarChart(
|
|
118
|
+
function horizontalBarChart(
|
|
119
|
+
data,
|
|
120
|
+
{
|
|
121
|
+
title,
|
|
122
|
+
formatter = (value) => String(value),
|
|
123
|
+
getValue,
|
|
124
|
+
getLabel,
|
|
125
|
+
getColor,
|
|
126
|
+
fontFamily = DEFAULT_FONT_FAMILY,
|
|
127
|
+
},
|
|
128
|
+
) {
|
|
86
129
|
const width = 980;
|
|
87
130
|
const height = 360;
|
|
88
|
-
const longestLabelLength = data.reduce(
|
|
131
|
+
const longestLabelLength = data.reduce(
|
|
132
|
+
(max, entry) => Math.max(max, String(getLabel(entry) || '').length),
|
|
133
|
+
0,
|
|
134
|
+
);
|
|
89
135
|
const margin = {
|
|
90
136
|
top: 46,
|
|
91
137
|
right: 100,
|
|
@@ -94,39 +140,56 @@ function horizontalBarChart(data, { title, formatter = (value) => String(value),
|
|
|
94
140
|
};
|
|
95
141
|
const plotWidth = width - margin.left - margin.right;
|
|
96
142
|
const barGap = 18;
|
|
97
|
-
const barHeight = Math.min(
|
|
143
|
+
const barHeight = Math.min(
|
|
144
|
+
28,
|
|
145
|
+
(height - margin.top - margin.bottom - barGap * (data.length - 1)) / Math.max(data.length, 1),
|
|
146
|
+
);
|
|
98
147
|
const maxValue = Math.max(...data.map(getValue), 1);
|
|
99
148
|
|
|
100
|
-
return svgDoc(
|
|
149
|
+
return svgDoc(
|
|
150
|
+
width,
|
|
151
|
+
height,
|
|
152
|
+
`
|
|
101
153
|
<rect width="${width}" height="${height}" rx="24" fill="#ffffff"/>
|
|
102
154
|
<text x="${margin.left}" y="28" font-size="18" font-family="${fontFamily}" font-weight="700" fill="#122033">${escapeXml(title)}</text>
|
|
103
|
-
${data
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
155
|
+
${data
|
|
156
|
+
.map((entry, index) => {
|
|
157
|
+
const y = margin.top + index * (barHeight + barGap);
|
|
158
|
+
const value = getValue(entry);
|
|
159
|
+
const barWidth = clamp((value / maxValue) * plotWidth, 0, plotWidth);
|
|
160
|
+
return `
|
|
108
161
|
<text x="${margin.left - 18}" y="${y + barHeight / 2 + 4}" text-anchor="end" font-size="13" font-family="${fontFamily}" fill="#122033">${escapeXml(truncateSvgLabel(getLabel(entry), 30))}</text>
|
|
109
162
|
<rect x="${margin.left}" y="${y}" width="${plotWidth}" height="${barHeight}" rx="12" fill="#eef3f8"/>
|
|
110
163
|
<rect x="${margin.left}" y="${y}" width="${barWidth}" height="${barHeight}" rx="12" fill="${getColor(entry)}"/>
|
|
111
164
|
<text x="${margin.left + plotWidth + 12}" y="${y + barHeight / 2 + 4}" font-size="12" font-family="${fontFamily}" fill="#475569">${escapeXml(formatter(value))}</text>
|
|
112
165
|
`;
|
|
113
|
-
|
|
114
|
-
|
|
166
|
+
})
|
|
167
|
+
.join('')}
|
|
168
|
+
`,
|
|
169
|
+
);
|
|
115
170
|
}
|
|
116
171
|
|
|
117
|
-
function stackedBarChart(
|
|
172
|
+
function stackedBarChart(
|
|
173
|
+
data,
|
|
174
|
+
{ title, segments, formatter = (value) => String(value), fontFamily = DEFAULT_FONT_FAMILY },
|
|
175
|
+
) {
|
|
118
176
|
const width = 980;
|
|
119
177
|
const height = 380;
|
|
120
178
|
const margin = { top: 52, right: 30, bottom: 56, left: 74 };
|
|
121
179
|
const plotWidth = width - margin.left - margin.right;
|
|
122
180
|
const plotHeight = height - margin.top - margin.bottom;
|
|
123
|
-
const totals = data.map((entry) =>
|
|
181
|
+
const totals = data.map((entry) =>
|
|
182
|
+
segments.reduce((sum, segment) => sum + (Number(entry[segment.key]) || 0), 0),
|
|
183
|
+
);
|
|
124
184
|
const maxValue = Math.max(...totals, 1);
|
|
125
185
|
const barWidth = Math.max(10, plotWidth / Math.max(data.length * 1.8, 1));
|
|
126
186
|
const gap = data.length > 1 ? (plotWidth - data.length * barWidth) / (data.length - 1) : 0;
|
|
127
187
|
const labelStep = Math.max(1, Math.ceil(data.length / 7));
|
|
128
188
|
|
|
129
|
-
return svgDoc(
|
|
189
|
+
return svgDoc(
|
|
190
|
+
width,
|
|
191
|
+
height,
|
|
192
|
+
`
|
|
130
193
|
<rect width="${width}" height="${height}" rx="24" fill="#ffffff"/>
|
|
131
194
|
<text x="${margin.left}" y="30" font-size="18" font-family="${fontFamily}" font-weight="700" fill="#122033">${escapeXml(title)}</text>
|
|
132
195
|
${Array.from({ length: 5 }, (_, index) => {
|
|
@@ -137,26 +200,36 @@ function stackedBarChart(data, { title, segments, formatter = (value) => String(
|
|
|
137
200
|
<text x="${margin.left - 12}" y="${y + 4}" text-anchor="end" font-size="11" font-family="${fontFamily}" fill="#5c6b7e">${escapeXml(formatter(value))}</text>
|
|
138
201
|
`;
|
|
139
202
|
}).join('')}
|
|
140
|
-
${data
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
203
|
+
${data
|
|
204
|
+
.map((entry, index) => {
|
|
205
|
+
const x = margin.left + index * (barWidth + gap);
|
|
206
|
+
let offset = 0;
|
|
207
|
+
const rects = segments
|
|
208
|
+
.map((segment) => {
|
|
209
|
+
const value = Number(entry[segment.key]) || 0;
|
|
210
|
+
const h = maxValue > 0 ? (value / maxValue) * plotHeight : 0;
|
|
211
|
+
const y = margin.top + plotHeight - offset - h;
|
|
212
|
+
offset += h;
|
|
213
|
+
return `<rect x="${x}" y="${y}" width="${barWidth}" height="${h}" rx="6" fill="${segment.color}"/>`;
|
|
214
|
+
})
|
|
215
|
+
.join('');
|
|
216
|
+
const label =
|
|
217
|
+
index % labelStep === 0 || index === data.length - 1
|
|
218
|
+
? `<text x="${x + barWidth / 2}" y="${height - 18}" text-anchor="middle" font-size="11" font-family="${fontFamily}" fill="#5c6b7e">${escapeXml(entry.label)}</text>`
|
|
219
|
+
: '';
|
|
220
|
+
return `${rects}${label}`;
|
|
221
|
+
})
|
|
222
|
+
.join('')}
|
|
223
|
+
${segments
|
|
224
|
+
.map(
|
|
225
|
+
(segment, index) => `
|
|
156
226
|
<rect x="${margin.left + (index % 3) * 156}" y="${height - 34 - Math.floor(index / 3) * 18}" width="12" height="12" rx="3" fill="${segment.color}"/>
|
|
157
227
|
<text x="${margin.left + 18 + (index % 3) * 156}" y="${height - 24 - Math.floor(index / 3) * 18}" font-size="11" font-family="${fontFamily}" fill="#334155">${escapeXml(segment.label)}</text>
|
|
158
|
-
|
|
159
|
-
|
|
228
|
+
`,
|
|
229
|
+
)
|
|
230
|
+
.join('')}
|
|
231
|
+
`,
|
|
232
|
+
);
|
|
160
233
|
}
|
|
161
234
|
|
|
162
235
|
module.exports = {
|
package/server/report/index.js
CHANGED
|
@@ -292,11 +292,31 @@ function createChartAssets(reportData) {
|
|
|
292
292
|
title: reportData.text.charts.tokenTrend,
|
|
293
293
|
formatter: (value) => formatCompactAxis(value, reportData.meta.language),
|
|
294
294
|
segments: [
|
|
295
|
-
{
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
295
|
+
{
|
|
296
|
+
key: 'input',
|
|
297
|
+
label: translate(reportData.meta.language, 'common.input'),
|
|
298
|
+
color: '#0f766e',
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
key: 'output',
|
|
302
|
+
label: translate(reportData.meta.language, 'common.output'),
|
|
303
|
+
color: '#1d4ed8',
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
key: 'cacheWrite',
|
|
307
|
+
label: translate(reportData.meta.language, 'common.cacheWrite'),
|
|
308
|
+
color: '#b45309',
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
key: 'cacheRead',
|
|
312
|
+
label: translate(reportData.meta.language, 'common.cacheRead'),
|
|
313
|
+
color: '#7c3aed',
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
key: 'thinking',
|
|
317
|
+
label: translate(reportData.meta.language, 'common.thinking'),
|
|
318
|
+
color: '#be185d',
|
|
319
|
+
},
|
|
300
320
|
],
|
|
301
321
|
}),
|
|
302
322
|
};
|