ccgauge 1.0.3 → 1.0.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.
Files changed (97) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-build-manifest.json +45 -45
  3. package/.next/standalone/.next/app-path-routes-manifest.json +8 -8
  4. package/.next/standalone/.next/build-manifest.json +2 -2
  5. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  6. package/.next/standalone/.next/server/app/api/blocks/route_client-reference-manifest.js +1 -1
  7. package/.next/standalone/.next/server/app/api/export/usage/route_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/api/pricing/route_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/api/scan/route_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/api/sessions/route_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/api/usage/route.js +1 -1
  13. package/.next/standalone/.next/server/app/api/usage/route_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/models/page.js +1 -1
  15. package/.next/standalone/.next/server/app/models/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/page.js +1 -1
  17. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/projects/[id]/page.js +1 -1
  19. package/.next/standalone/.next/server/app/projects/[id]/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  21. package/.next/standalone/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/settings/page.js +1 -1
  24. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  25. package/.next/standalone/.next/server/app/usage/page.js +1 -1
  26. package/.next/standalone/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/app-paths-manifest.json +8 -8
  28. package/.next/standalone/.next/server/chunks/517.js +1 -1
  29. package/.next/standalone/.next/server/chunks/567.js +2 -2
  30. package/.next/standalone/.next/server/chunks/98.js +1 -1
  31. package/.next/standalone/.next/server/functions-config-manifest.json +1 -1
  32. package/.next/standalone/.next/server/pages/500.html +1 -1
  33. package/.next/standalone/.next/static/chunks/148-6c2eaf5508bfe739.js +1 -0
  34. package/.next/standalone/.next/static/chunks/930-ca5c6f8b5cb6ac3d.js +1 -0
  35. package/.next/standalone/.next/static/chunks/app/layout-4f3538437c5e8366.js +1 -0
  36. package/.next/standalone/.next/static/chunks/app/page-3cda7f70ecf5017a.js +1 -0
  37. package/.next/standalone/.next/static/chunks/app/settings/page-1ba7c4a4c0fae2f8.js +1 -0
  38. package/.next/standalone/.next/static/css/{406e067663b8b429.css → fbd2c395e5bf32cb.css} +1 -1
  39. package/.next/standalone/node_modules/next/node_modules/@img/sharp-darwin-arm64/LICENSE +191 -0
  40. package/.next/standalone/node_modules/next/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node +0 -0
  41. package/.next/standalone/node_modules/next/node_modules/@img/sharp-darwin-arm64/package.json +40 -0
  42. package/.next/standalone/node_modules/next/node_modules/@img/sharp-libvips-darwin-arm64/lib/index.js +1 -0
  43. package/.next/standalone/node_modules/next/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.8.17.3.dylib +0 -0
  44. package/.next/standalone/node_modules/next/node_modules/@img/sharp-libvips-darwin-arm64/package.json +36 -0
  45. package/.next/standalone/node_modules/next/node_modules/@img/sharp-libvips-darwin-arm64/versions.json +30 -0
  46. package/.next/standalone/node_modules/next/node_modules/postcss/package.json +0 -0
  47. package/.next/standalone/node_modules/next/node_modules/sharp/lib/channel.js +177 -0
  48. package/.next/standalone/node_modules/next/node_modules/sharp/lib/colour.js +195 -0
  49. package/.next/standalone/node_modules/next/node_modules/sharp/lib/composite.js +212 -0
  50. package/.next/standalone/node_modules/next/node_modules/sharp/lib/constructor.js +499 -0
  51. package/.next/standalone/node_modules/next/node_modules/sharp/lib/index.js +16 -0
  52. package/.next/standalone/node_modules/next/node_modules/sharp/lib/input.js +809 -0
  53. package/.next/standalone/node_modules/next/node_modules/sharp/lib/is.js +143 -0
  54. package/.next/standalone/node_modules/next/node_modules/sharp/lib/libvips.js +207 -0
  55. package/.next/standalone/node_modules/next/node_modules/sharp/lib/operation.js +1016 -0
  56. package/.next/standalone/node_modules/next/node_modules/sharp/lib/output.js +1666 -0
  57. package/.next/standalone/node_modules/next/node_modules/sharp/lib/resize.js +595 -0
  58. package/.next/standalone/node_modules/next/node_modules/sharp/lib/sharp.js +121 -0
  59. package/.next/standalone/node_modules/next/node_modules/sharp/lib/utility.js +291 -0
  60. package/.next/standalone/node_modules/next/node_modules/sharp/package.json +202 -0
  61. package/.next/standalone/node_modules/semver/classes/comparator.js +143 -0
  62. package/.next/standalone/node_modules/semver/classes/range.js +557 -0
  63. package/.next/standalone/node_modules/semver/classes/semver.js +333 -0
  64. package/.next/standalone/node_modules/semver/functions/cmp.js +54 -0
  65. package/.next/standalone/node_modules/semver/functions/coerce.js +62 -0
  66. package/.next/standalone/node_modules/semver/functions/compare.js +7 -0
  67. package/.next/standalone/node_modules/semver/functions/eq.js +5 -0
  68. package/.next/standalone/node_modules/semver/functions/gt.js +5 -0
  69. package/.next/standalone/node_modules/semver/functions/gte.js +5 -0
  70. package/.next/standalone/node_modules/semver/functions/lt.js +5 -0
  71. package/.next/standalone/node_modules/semver/functions/lte.js +5 -0
  72. package/.next/standalone/node_modules/semver/functions/neq.js +5 -0
  73. package/.next/standalone/node_modules/semver/functions/parse.js +18 -0
  74. package/.next/standalone/node_modules/semver/functions/satisfies.js +12 -0
  75. package/.next/standalone/node_modules/semver/internal/constants.js +37 -0
  76. package/.next/standalone/node_modules/semver/internal/debug.js +11 -0
  77. package/.next/standalone/node_modules/semver/internal/identifiers.js +29 -0
  78. package/.next/standalone/node_modules/semver/internal/lrucache.js +42 -0
  79. package/.next/standalone/node_modules/semver/internal/parse-options.js +17 -0
  80. package/.next/standalone/node_modules/semver/internal/re.js +223 -0
  81. package/.next/standalone/node_modules/semver/package.json +78 -0
  82. package/.next/standalone/package.json +13 -2
  83. package/.next/standalone/public/favicon.svg +19 -5
  84. package/CHANGELOG.md +64 -0
  85. package/README.md +2 -0
  86. package/README.zh-CN.md +5 -2
  87. package/bin/cli.mjs +10 -1
  88. package/dist/mcp/server.mjs +12 -12
  89. package/dist/report/index.mjs +13 -2
  90. package/package.json +29 -16
  91. package/.next/standalone/.next/static/chunks/148-0a1e1b0207b89e3f.js +0 -1
  92. package/.next/standalone/.next/static/chunks/930-3035d0b294080d0b.js +0 -1
  93. package/.next/standalone/.next/static/chunks/app/layout-2512ccdfb13aeb17.js +0 -1
  94. package/.next/standalone/.next/static/chunks/app/page-19d3e77d4aa35a63.js +0 -1
  95. package/.next/standalone/.next/static/chunks/app/settings/page-cfeb089549c94f88.js +0 -1
  96. /package/.next/standalone/.next/static/{alqi5oQtTQUdpxp2x0yAt → ir1LZCnQKkiNUVXLprtzh}/_buildManifest.js +0 -0
  97. /package/.next/standalone/.next/static/{alqi5oQtTQUdpxp2x0yAt → ir1LZCnQKkiNUVXLprtzh}/_ssgManifest.js +0 -0
@@ -0,0 +1,223 @@
1
+ 'use strict'
2
+
3
+ const {
4
+ MAX_SAFE_COMPONENT_LENGTH,
5
+ MAX_SAFE_BUILD_LENGTH,
6
+ MAX_LENGTH,
7
+ } = require('./constants')
8
+ const debug = require('./debug')
9
+ exports = module.exports = {}
10
+
11
+ // The actual regexps go on exports.re
12
+ const re = exports.re = []
13
+ const safeRe = exports.safeRe = []
14
+ const src = exports.src = []
15
+ const safeSrc = exports.safeSrc = []
16
+ const t = exports.t = {}
17
+ let R = 0
18
+
19
+ const LETTERDASHNUMBER = '[a-zA-Z0-9-]'
20
+
21
+ // Replace some greedy regex tokens to prevent regex dos issues. These regex are
22
+ // used internally via the safeRe object since all inputs in this library get
23
+ // normalized first to trim and collapse all extra whitespace. The original
24
+ // regexes are exported for userland consumption and lower level usage. A
25
+ // future breaking change could export the safer regex only with a note that
26
+ // all input should have extra whitespace removed.
27
+ const safeRegexReplacements = [
28
+ ['\\s', 1],
29
+ ['\\d', MAX_LENGTH],
30
+ [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
31
+ ]
32
+
33
+ const makeSafeRegex = (value) => {
34
+ for (const [token, max] of safeRegexReplacements) {
35
+ value = value
36
+ .split(`${token}*`).join(`${token}{0,${max}}`)
37
+ .split(`${token}+`).join(`${token}{1,${max}}`)
38
+ }
39
+ return value
40
+ }
41
+
42
+ const createToken = (name, value, isGlobal) => {
43
+ const safe = makeSafeRegex(value)
44
+ const index = R++
45
+ debug(name, index, value)
46
+ t[name] = index
47
+ src[index] = value
48
+ safeSrc[index] = safe
49
+ re[index] = new RegExp(value, isGlobal ? 'g' : undefined)
50
+ safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined)
51
+ }
52
+
53
+ // The following Regular Expressions can be used for tokenizing,
54
+ // validating, and parsing SemVer version strings.
55
+
56
+ // ## Numeric Identifier
57
+ // A single `0`, or a non-zero digit followed by zero or more digits.
58
+
59
+ createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*')
60
+ createToken('NUMERICIDENTIFIERLOOSE', '\\d+')
61
+
62
+ // ## Non-numeric Identifier
63
+ // Zero or more digits, followed by a letter or hyphen, and then zero or
64
+ // more letters, digits, or hyphens.
65
+
66
+ createToken('NONNUMERICIDENTIFIER', `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`)
67
+
68
+ // ## Main Version
69
+ // Three dot-separated numeric identifiers.
70
+
71
+ createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` +
72
+ `(${src[t.NUMERICIDENTIFIER]})\\.` +
73
+ `(${src[t.NUMERICIDENTIFIER]})`)
74
+
75
+ createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
76
+ `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
77
+ `(${src[t.NUMERICIDENTIFIERLOOSE]})`)
78
+
79
+ // ## Pre-release Version Identifier
80
+ // A numeric identifier, or a non-numeric identifier.
81
+ // Non-numeric identifiers include numeric identifiers but can be longer.
82
+ // Therefore non-numeric identifiers must go first.
83
+
84
+ createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NONNUMERICIDENTIFIER]
85
+ }|${src[t.NUMERICIDENTIFIER]})`)
86
+
87
+ createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NONNUMERICIDENTIFIER]
88
+ }|${src[t.NUMERICIDENTIFIERLOOSE]})`)
89
+
90
+ // ## Pre-release Version
91
+ // Hyphen, followed by one or more dot-separated pre-release version
92
+ // identifiers.
93
+
94
+ createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]
95
+ }(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`)
96
+
97
+ createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]
98
+ }(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`)
99
+
100
+ // ## Build Metadata Identifier
101
+ // Any combination of digits, letters, or hyphens.
102
+
103
+ createToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`)
104
+
105
+ // ## Build Metadata
106
+ // Plus sign, followed by one or more period-separated build metadata
107
+ // identifiers.
108
+
109
+ createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER]
110
+ }(?:\\.${src[t.BUILDIDENTIFIER]})*))`)
111
+
112
+ // ## Full Version String
113
+ // A main version, followed optionally by a pre-release version and
114
+ // build metadata.
115
+
116
+ // Note that the only major, minor, patch, and pre-release sections of
117
+ // the version string are capturing groups. The build metadata is not a
118
+ // capturing group, because it should not ever be used in version
119
+ // comparison.
120
+
121
+ createToken('FULLPLAIN', `v?${src[t.MAINVERSION]
122
+ }${src[t.PRERELEASE]}?${
123
+ src[t.BUILD]}?`)
124
+
125
+ createToken('FULL', `^${src[t.FULLPLAIN]}$`)
126
+
127
+ // like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
128
+ // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
129
+ // common in the npm registry.
130
+ createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE]
131
+ }${src[t.PRERELEASELOOSE]}?${
132
+ src[t.BUILD]}?`)
133
+
134
+ createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`)
135
+
136
+ createToken('GTLT', '((?:<|>)?=?)')
137
+
138
+ // Something like "2.*" or "1.2.x".
139
+ // Note that "x.x" is a valid xRange identifer, meaning "any version"
140
+ // Only the first item is strictly required.
141
+ createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`)
142
+ createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`)
143
+
144
+ createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` +
145
+ `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
146
+ `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
147
+ `(?:${src[t.PRERELEASE]})?${
148
+ src[t.BUILD]}?` +
149
+ `)?)?`)
150
+
151
+ createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +
152
+ `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
153
+ `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
154
+ `(?:${src[t.PRERELEASELOOSE]})?${
155
+ src[t.BUILD]}?` +
156
+ `)?)?`)
157
+
158
+ createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`)
159
+ createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`)
160
+
161
+ // Coercion.
162
+ // Extract anything that could conceivably be a part of a valid semver
163
+ createToken('COERCEPLAIN', `${'(^|[^\\d])' +
164
+ '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
165
+ `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
166
+ `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`)
167
+ createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`)
168
+ createToken('COERCEFULL', src[t.COERCEPLAIN] +
169
+ `(?:${src[t.PRERELEASE]})?` +
170
+ `(?:${src[t.BUILD]})?` +
171
+ `(?:$|[^\\d])`)
172
+ createToken('COERCERTL', src[t.COERCE], true)
173
+ createToken('COERCERTLFULL', src[t.COERCEFULL], true)
174
+
175
+ // Tilde ranges.
176
+ // Meaning is "reasonably at or greater than"
177
+ createToken('LONETILDE', '(?:~>?)')
178
+
179
+ createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true)
180
+ exports.tildeTrimReplace = '$1~'
181
+
182
+ createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`)
183
+ createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`)
184
+
185
+ // Caret ranges.
186
+ // Meaning is "at least and backwards compatible with"
187
+ createToken('LONECARET', '(?:\\^)')
188
+
189
+ createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true)
190
+ exports.caretTrimReplace = '$1^'
191
+
192
+ createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`)
193
+ createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`)
194
+
195
+ // A simple gt/lt/eq thing, or just "" to indicate "any version"
196
+ createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`)
197
+ createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`)
198
+
199
+ // An expression to strip any whitespace between the gtlt and the thing
200
+ // it modifies, so that `> 1.2.3` ==> `>1.2.3`
201
+ createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT]
202
+ }\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true)
203
+ exports.comparatorTrimReplace = '$1$2$3'
204
+
205
+ // Something like `1.2.3 - 1.2.4`
206
+ // Note that these all use the loose form, because they'll be
207
+ // checked against either the strict or loose comparator form
208
+ // later.
209
+ createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` +
210
+ `\\s+-\\s+` +
211
+ `(${src[t.XRANGEPLAIN]})` +
212
+ `\\s*$`)
213
+
214
+ createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
215
+ `\\s+-\\s+` +
216
+ `(${src[t.XRANGEPLAINLOOSE]})` +
217
+ `\\s*$`)
218
+
219
+ // Star ranges basically just allow anything at all.
220
+ createToken('STAR', '(<|>)?=?\\s*\\*')
221
+ // >=0.0.0 is like a star
222
+ createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$')
223
+ createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$')
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "semver",
3
+ "version": "7.7.4",
4
+ "description": "The semantic version parser used by npm.",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "tap",
8
+ "snap": "tap",
9
+ "lint": "npm run eslint",
10
+ "postlint": "template-oss-check",
11
+ "lintfix": "npm run eslint -- --fix",
12
+ "posttest": "npm run lint",
13
+ "template-oss-apply": "template-oss-apply --force",
14
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
15
+ },
16
+ "devDependencies": {
17
+ "@npmcli/eslint-config": "^6.0.0",
18
+ "@npmcli/template-oss": "4.29.0",
19
+ "benchmark": "^2.1.4",
20
+ "tap": "^16.0.0"
21
+ },
22
+ "license": "ISC",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/npm/node-semver.git"
26
+ },
27
+ "bin": {
28
+ "semver": "bin/semver.js"
29
+ },
30
+ "files": [
31
+ "bin/",
32
+ "lib/",
33
+ "classes/",
34
+ "functions/",
35
+ "internal/",
36
+ "ranges/",
37
+ "index.js",
38
+ "preload.js",
39
+ "range.bnf"
40
+ ],
41
+ "tap": {
42
+ "timeout": 30,
43
+ "coverage-map": "map.js",
44
+ "nyc-arg": [
45
+ "--exclude",
46
+ "tap-snapshots/**"
47
+ ]
48
+ },
49
+ "engines": {
50
+ "node": ">=10"
51
+ },
52
+ "author": "GitHub Inc.",
53
+ "templateOSS": {
54
+ "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
55
+ "version": "4.29.0",
56
+ "engines": ">=10",
57
+ "distPaths": [
58
+ "classes/",
59
+ "functions/",
60
+ "internal/",
61
+ "ranges/",
62
+ "index.js",
63
+ "preload.js",
64
+ "range.bnf"
65
+ ],
66
+ "allowPaths": [
67
+ "/classes/",
68
+ "/functions/",
69
+ "/internal/",
70
+ "/ranges/",
71
+ "/index.js",
72
+ "/preload.js",
73
+ "/range.bnf",
74
+ "/benchmarks"
75
+ ],
76
+ "publish": "true"
77
+ }
78
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccgauge",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Local web dashboard for Claude Code and OpenAI Codex CLI token usage and cost",
5
5
  "keywords": [
6
6
  "claude",
@@ -64,10 +64,16 @@
64
64
  "start:next": "next start -p 3737",
65
65
  "lint": "eslint .",
66
66
  "typecheck": "tsc --noEmit",
67
- "test": "node --experimental-strip-types --no-warnings scripts/test-codex-parser.mjs",
67
+ "test": "node --experimental-strip-types --no-warnings scripts/test-codex-parser.mjs && node --experimental-strip-types --no-warnings scripts/test-turns.mjs && node --experimental-strip-types --no-warnings scripts/test-source-merge.mjs && node --experimental-strip-types --no-warnings scripts/test-cost-from-usage.mjs && node --experimental-strip-types --no-warnings scripts/test-range.mjs && node scripts/check-parser-versions.mjs && node scripts/check-readme-images.mjs",
68
68
  "test:mcp": "node scripts/test-mcp-server.mjs",
69
69
  "clean": "node -e \"for (const p of ['.next','node_modules','tsconfig.tsbuildinfo']) require('node:fs').rmSync(p,{recursive:true,force:true})\"",
70
70
  "screenshots": "node scripts/screenshots.mjs",
71
+ "site:dev": "cd site && astro dev --port 4321",
72
+ "site:build": "cd site && astro build",
73
+ "site:preview": "cd site && astro preview --port 4322",
74
+ "site:check": "cd site && astro check",
75
+ "site:gen:placeholders": "node site/scripts/gen-placeholders.mjs",
76
+ "site:clean": "node -e \"for (const p of ['site/dist','site/.astro','site/node_modules']) require('node:fs').rmSync(p,{recursive:true,force:true})\"",
71
77
  "prepack": "pnpm build"
72
78
  },
73
79
  "dependencies": {
@@ -77,10 +83,15 @@
77
83
  "open": "^10.1.0"
78
84
  },
79
85
  "devDependencies": {
86
+ "@astrojs/check": "^0.9.4",
87
+ "@astrojs/tailwind": "^5.1.4",
80
88
  "@eslint/eslintrc": "^3.3.5",
89
+ "@fontsource-variable/geist": "^5.1.1",
90
+ "@fontsource-variable/geist-mono": "^5.1.1",
81
91
  "@types/node": "^22.10.0",
82
92
  "@types/react": "^19.0.0",
83
93
  "@types/react-dom": "^19.0.0",
94
+ "astro": "^4.16.18",
84
95
  "autoprefixer": "^10.4.20",
85
96
  "clsx": "^2.1.1",
86
97
  "date-fns": "^4.1.0",
@@ -1,7 +1,21 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
- <rect width="64" height="64" rx="14" fill="#4F46E5"/>
3
- <path d="M14 41 A18 18 0 0 1 50 41" stroke="#fff" stroke-opacity="0.32" stroke-width="4.5" stroke-linecap="round"/>
4
- <path d="M14 41 A18 18 0 0 1 43.2 25.4" stroke="#fff" stroke-width="4.5" stroke-linecap="round"/>
5
- <line x1="32" y1="41" x2="42" y2="27" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/>
6
- <circle cx="32" cy="41" r="3" fill="#fff"/>
2
+ <title>ccgauge</title>
3
+ <rect x="3" y="3" width="58" height="58" rx="16" fill="#6366F1"/>
4
+ <rect x="3.75" y="3.75" width="56.5" height="56.5" rx="15.25" stroke="#FFFFFF" stroke-opacity="0.18" stroke-width="1.5"/>
5
+ <path d="M15 39.5 A17 17 0 0 1 49 39.5" stroke="#FFFFFF" stroke-opacity="0.24" stroke-width="5" stroke-linecap="round"/>
6
+ <path d="M20.8 39.5 A11.2 11.2 0 0 1 43.2 39.5" stroke="#FFFFFF" stroke-opacity="0.2" stroke-width="1.8" stroke-linecap="round"/>
7
+ <path d="M15 39.5 A17 17 0 0 1 42.8 26" stroke="#FFFFFF" stroke-width="5" stroke-linecap="round"/>
8
+ <g stroke="#FFFFFF" stroke-linecap="round" stroke-width="2" stroke-opacity="0.54">
9
+ <path d="M18.1 34.2 L15 32.4"/>
10
+ <path d="M24 28.5 L22.3 25.5"/>
11
+ <path d="M32 26.2 L32 22.8"/>
12
+ <path d="M40 28.5 L41.7 25.5"/>
13
+ <path d="M45.9 34.2 L49 32.4"/>
14
+ </g>
15
+ <path d="M32 39.5 L42.8 26" stroke="#FFFFFF" stroke-width="3.4" stroke-linecap="round"/>
16
+ <circle cx="32" cy="39.5" r="4.8" fill="#FFFFFF"/>
17
+ <circle cx="32" cy="39.5" r="2" fill="#4F46E5"/>
18
+ <rect x="17" y="46" width="7" height="5" rx="2" fill="#34D399"/>
19
+ <rect x="28.5" y="43" width="7" height="8" rx="2" fill="#FBBF24"/>
20
+ <rect x="40" y="45" width="7" height="6" rx="2" fill="#93C5FD"/>
7
21
  </svg>
package/CHANGELOG.md CHANGED
@@ -5,6 +5,70 @@ All notable changes to **ccgauge** are documented here.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
6
6
  this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.4] — 2026-05-18
9
+
10
+ Correctness fixes + much stronger test coverage, plus a brand refresh
11
+ and a marketing-site restructure. No new runtime features.
12
+
13
+ ### Fixed
14
+
15
+ - **Windows path sanitization.** `sanitizeForUser` now also strips
16
+ forward-slashed, JSON-escaped, and long-path (`\\?\`) variants of
17
+ `homedir()`, not just the literal `C:\Users\<name>` form. macOS /
18
+ Linux behaviour unchanged.
19
+ - **5h-block empty state** follows the active source —
20
+ `?source=codex` no longer says "Send a message in Claude Code".
21
+ Same fix on the Codex tab inside the All view.
22
+ - **`combineTimeBuckets` shared-reference bug.** Shallow-cloned model
23
+ entries were aliased back into the indexer's aggregator cache, so
24
+ downstream mutations could poison subsequent reads. Deep-cloned on
25
+ insertion; pinned by a new test.
26
+ - **`safeMcpHandler` non-Error throws** are now wrapped + scrubbed
27
+ before re-throw; the previous branch silently fell through, shipping
28
+ unscrubbed payloads into the MCP envelope.
29
+
30
+ ### Added
31
+
32
+ - **6 test / drift scripts**, all wired into `pnpm test`:
33
+ `test-turns`, `test-source-merge`, `test-cost-from-usage`,
34
+ `test-range` (fixture-based unit tests for the four core code
35
+ paths), plus `check-parser-versions` and `check-readme-images` (CI
36
+ drift guards for silently-stale-cache and broken-npm-image
37
+ regressions).
38
+
39
+ ### Changed
40
+
41
+ - **Refined gauge brand mark**, unified across the dashboard, the
42
+ marketing site, and both favicons. Cleaner geometry (centre at
43
+ (32, 41), radius 18; arc + needle terminating on the dial rim),
44
+ Indigo-400 → -600 gradient background, white-ring pivot. New shared
45
+ `<LogoMark>` component on the marketing site so its Nav + Footer
46
+ now use the same mark as the dashboard.
47
+ - **Marketing site is source-only.** Removed `site/package.json` and
48
+ `site/pnpm-lock.yaml`; Astro deps live in root `devDependencies`,
49
+ commands are explicit `pnpm site:*`. Still excluded from the npm
50
+ tarball (`pnpm pack --dry-run | grep -c '^site/'` → `0`).
51
+ - **Theme-aware product screenshots.** New `<ThemedScreenshot>`
52
+ component swaps between dark / light captures via the
53
+ `.theme-light` class on `<html>`. 24 captures (6 pages × 2 locales
54
+ × 2 themes) generated by an expanded `scripts/screenshots.mjs`.
55
+ - **OG cards** regenerated at higher fidelity.
56
+ - **`cost_estimator` MCP tool** description spells out that reasoning
57
+ tokens are already counted inside `output_tokens` — don't
58
+ double-count.
59
+ - **Activity heatmap tooltip** finally renders the share / of-peak
60
+ labels that were defined but never used.
61
+ - **`CacheCreationBlock` type** extracted in `parse-jsonl.ts`.
62
+ - **CLI `readState()`** type-guards `pid` / `url` / `logFile`.
63
+
64
+ ### Internal
65
+
66
+ - MCP server warm-up comment clarifies the fire-and-forget
67
+ `getMcpIndexerReady()` is a cold-start shave — tool handlers still
68
+ await the same memoized init promise.
69
+ - `AGENTS.md` + bundled READMEs updated for the source-only site
70
+ layout and the new `pnpm site:*` command set.
71
+
8
72
  ## [1.0.3] — 2026-05-15
9
73
 
10
74
  A focused **MCP server** correctness + performance + ergonomics pass,
package/README.md CHANGED
@@ -461,6 +461,8 @@ pnpm test # codex parser smoke test (Node 22+)
461
461
  pnpm build # next build + copy static into .next/standalone
462
462
  pnpm start # run bin/cli.mjs against the standalone build
463
463
  pnpm screenshots # regenerate docs/screenshots/*.png
464
+ pnpm site:dev # marketing site dev server, http://localhost:4321
465
+ pnpm site:build # build only the site/ marketing site
464
466
  pnpm clean # rm -rf .next node_modules
465
467
  ```
466
468
 
package/README.zh-CN.md CHANGED
@@ -454,6 +454,8 @@ pnpm test # codex parser 烟测(Node 22+)
454
454
  pnpm build # next build + 把 static 拷进 .next/standalone
455
455
  pnpm start # 用 bin/cli.mjs 跑 standalone 产物
456
456
  pnpm screenshots # 重新生成 docs/screenshots/*.png
457
+ pnpm site:dev # 产品官网开发服务,http://localhost:4321
458
+ pnpm site:build # 只构建 site/ 产品官网
457
459
  pnpm clean # rm -rf .next node_modules
458
460
  ```
459
461
 
@@ -508,10 +510,11 @@ pnpm publish --access public # 会自动先跑 pnpm build(prepublishOnly)
508
510
  ## 产品官网
509
511
 
510
512
  产品官网(Astro + Tailwind 自建、中英双语、暗 / 亮主题、独立部署)放在
511
- [`site/`](./site/) 目录。它跟着主仓库一起在 git 里,但**不会**进 npm 包。
513
+ [`site/`](./site/) 目录。它跟着主仓库一起在 git 里,但**不会**进 npm 包;
514
+ 命令和依赖统一由根目录 `package.json` 管理。
512
515
 
513
516
  ```bash
514
- cd site && pnpm install && pnpm dev # http://localhost:4321
517
+ pnpm site:dev # http://localhost:4321
515
518
  ```
516
519
 
517
520
  构建 / 部署细节见 [`site/README.md`](./site/README.md)。
package/bin/cli.mjs CHANGED
@@ -587,9 +587,18 @@ async function readState() {
587
587
  try {
588
588
  const raw = await readFile(STATE_FILE, 'utf8');
589
589
  const parsed = JSON.parse(raw);
590
- if (!parsed || typeof parsed !== 'object') return null;
590
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return null;
591
591
  // Treat unknown / future versions as stale (auto-clean on next stop/start).
592
592
  if (parsed.version !== STATE_VERSION) return null;
593
+ // Type-guard the fields callers actually use — `stop`, `status`, and
594
+ // `restart` all assume these have the right shape. A hand-edited
595
+ // state.json with the right `version` but garbage in `pid` could
596
+ // otherwise crash `safeKill()` or `isProcessRunning()`.
597
+ if (typeof parsed.pid !== 'number' || !Number.isInteger(parsed.pid) || parsed.pid <= 0) {
598
+ return null;
599
+ }
600
+ if (typeof parsed.url !== 'string' || !parsed.url) return null;
601
+ if (typeof parsed.logFile !== 'string' || !parsed.logFile) return null;
593
602
  return parsed;
594
603
  } catch {
595
604
  return null;