tokentracker-cli 0.78.0 → 0.79.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/README.de.md +6 -2
- package/README.ja.md +6 -2
- package/README.ko.md +6 -2
- package/README.md +6 -2
- package/README.zh-CN.md +6 -2
- package/dashboard/dist/achievements/README.md +42 -0
- package/dashboard/dist/achievements/arctic-code-vault-contributor.png +0 -0
- package/dashboard/dist/achievements/big-day.png +0 -0
- package/dashboard/dist/achievements/galaxy-brain.png +0 -0
- package/dashboard/dist/achievements/heart-on-your-sleeve.png +0 -0
- package/dashboard/dist/achievements/marathoner.png +0 -0
- package/dashboard/dist/achievements/momentum.png +0 -0
- package/dashboard/dist/achievements/multitool.png +0 -0
- package/dashboard/dist/achievements/night-owl.png +0 -0
- package/dashboard/dist/achievements/open-sourcerer.png +0 -0
- package/dashboard/dist/achievements/pair-extraordinaire.png +0 -0
- package/dashboard/dist/achievements/podium.png +0 -0
- package/dashboard/dist/achievements/polyglot.png +0 -0
- package/dashboard/dist/achievements/project-devotion.png +0 -0
- package/dashboard/dist/achievements/project-hopper.png +0 -0
- package/dashboard/dist/achievements/proxima-pioneer.png +0 -0
- package/dashboard/dist/achievements/proxima-staffshipper.png +0 -0
- package/dashboard/dist/achievements/proxima-staffuser.png +0 -0
- package/dashboard/dist/achievements/public-sponsor.png +0 -0
- package/dashboard/dist/achievements/pull-shark.png +0 -0
- package/dashboard/dist/achievements/quickdraw.png +0 -0
- package/dashboard/dist/achievements/starstruck.png +0 -0
- package/dashboard/dist/achievements/streak.png +0 -0
- package/dashboard/dist/achievements/token-titan.png +0 -0
- package/dashboard/dist/achievements/trendsetter.png +0 -0
- package/dashboard/dist/achievements/veteran.png +0 -0
- package/dashboard/dist/achievements/weekend-warrior.png +0 -0
- package/dashboard/dist/achievements/wordsmith.png +0 -0
- package/dashboard/dist/assets/AchievementBadge-DE_M_FlI.js +1 -0
- package/dashboard/dist/assets/AchievementsPage-C5kgSyug.js +2 -0
- package/dashboard/dist/assets/AchievementsSection-Cqb39ASR.js +1 -0
- package/dashboard/dist/assets/ActivityHeatmap-BiQVnONF.js +42 -0
- package/dashboard/dist/assets/BadgeDetailModal-BpyfjXpH.js +1 -0
- package/dashboard/dist/assets/{Card-Ca_hYHhx.js → Card-TWMX7-tK.js} +1 -1
- package/dashboard/dist/assets/{ClawdAnimated-DSgOS5ND.js → ClawdAnimated-C0FIh-bc.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-o8uQVQxu.js → CommunityStatsModal-DLicuMsI.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-D1hi9XUf.js → ConfirmModal-DTWFK2AU.js} +1 -1
- package/dashboard/dist/assets/{Controls-CwnKP56V.js → Controls-BPZsw9dK.js} +1 -1
- package/dashboard/dist/assets/DashboardPage-BF5sIrjH.js +19 -0
- package/dashboard/dist/assets/DevicePage-tFqLpvgk.js +1 -0
- package/dashboard/dist/assets/DialogClose-CnHOktId.js +1 -0
- package/dashboard/dist/assets/DialogDescription-C5r4T-ji.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-DuuTVbUb.js → DialogTitle-BvBKLwS-.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-DpnitRKo.js → FadeIn-HTmqC5Me.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-D6zy-ADl.js → HeaderGithubStar-3pvJ0tHh.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-yUNp0VNe.js → IpCheckPage-MF1avXcU.js} +4 -4
- package/dashboard/dist/assets/{LandingPage-BvmpAaVn.js → LandingPage-Dh-tdgNM.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardAvatar-2WTIeXye.js → LeaderboardAvatar-nl7R3RcA.js} +1 -1
- package/dashboard/dist/assets/LeaderboardPage-DU3Wxclj.js +2 -0
- package/dashboard/dist/assets/LeaderboardProfileModal-COypUGpB.js +73 -0
- package/dashboard/dist/assets/{LeaderboardProfilePage-uJAng2JE.js → LeaderboardProfilePage-BKUWCZPu.js} +3 -3
- package/dashboard/dist/assets/{LimitsPage-D8UohgJm.js → LimitsPage-Df3iZHgC.js} +2 -2
- package/dashboard/dist/assets/{LocalOnlyNotice-Dv_BnDVV.js → LocalOnlyNotice-DLMgAyik.js} +1 -1
- package/dashboard/dist/assets/LoginPage-Dn3PBPwz.js +1 -0
- package/dashboard/dist/assets/PetPage-SLOM8HCy.js +1 -0
- package/dashboard/dist/assets/{PopoverPopup-CjzdZn-9.js → PopoverPopup-_kgqjYaH.js} +1 -1
- package/dashboard/dist/assets/ResetPasswordPage-cEiRF-Kj.js +1 -0
- package/dashboard/dist/assets/{Select-CHtQAiLD.js → Select-Bka2N1Os.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-Vjqvf8wO.js → SelectItemText-DLmcQo7p.js} +1 -1
- package/dashboard/dist/assets/SettingsPage-BkYr2MdU.js +1 -0
- package/dashboard/dist/assets/SkillsPage-D9AZ1iA9.js +1 -0
- package/dashboard/dist/assets/{WidgetsPage-4kqTtWfK.js → WidgetsPage-DV3zGrHr.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-DMMRpani.js → WrappedPage-CZj0iWky.js} +1 -1
- package/dashboard/dist/assets/agent-logos-CSt-wDz6.js +1 -0
- package/dashboard/dist/assets/{arrow-up-right-BAQYGZkR.js → arrow-up-right-D9Wvtol4.js} +1 -1
- package/dashboard/dist/assets/check-BherybaI.js +1 -0
- package/dashboard/dist/assets/{copy-gG_BLBs8.js → copy-LojMbXGV.js} +1 -1
- package/dashboard/dist/assets/{download-BQOcg3gT.js → download-C6yzefDC.js} +1 -1
- package/dashboard/dist/assets/flame-DTsJj_DM.js +1 -0
- package/dashboard/dist/assets/{format-tokens-CGK6lQAf.js → format-tokens-DYQOAytW.js} +1 -1
- package/dashboard/dist/assets/{info-C_BrDrcq.js → info-B8gESzFI.js} +1 -1
- package/dashboard/dist/assets/{link-2-DFwCBbIZ.js → link-2-DeSNrG_i.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-BMFI_BJ8.js → loader-circle-ANikx3BP.js} +1 -1
- package/dashboard/dist/assets/main-CC2hrzkh.js +1243 -0
- package/dashboard/dist/assets/main-KK0yAXww.css +1 -0
- package/dashboard/dist/assets/{trash-2-GeZ6IzgV.js → trash-2-2o4OmSfJ.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-pC8cmVof.js → use-community-stats-CB9fKR2A.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-DnFpPcA3.js → use-limits-display-prefs-CTm5gcWt.js} +1 -1
- package/dashboard/dist/assets/use-native-settings-Bsos8pTj.js +1 -0
- package/dashboard/dist/assets/{use-ordered-list-CbMroVZ8.js → use-ordered-list-2TnLOPaD.js} +1 -1
- package/dashboard/dist/assets/{use-quality-per-dollar-pref-Bn3Al6yX.js → use-quality-per-dollar-pref-Dj_YANL2.js} +1 -1
- package/dashboard/dist/assets/use-transform-Cz1NU7tm.js +1 -0
- package/dashboard/dist/assets/{use-usage-limits-D08q_Dr8.js → use-usage-limits-DZ1YjrcR.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-h3kqF52v.js → useCurrency-oJCdZSWF.js} +1 -1
- package/dashboard/dist/assets/{useScrollLock-9au2731u.js → useScrollLock-Cip5YmPI.js} +1 -1
- package/dashboard/dist/assets/zap-DjZw_VuX.js +1 -0
- package/dashboard/dist/index.html +2 -2
- package/dashboard/dist/share.html +2 -2
- package/package.json +1 -1
- package/src/commands/init.js +9 -4
- package/src/lib/local-api.js +113 -0
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +386 -35
- package/dashboard/dist/assets/ActivityHeatmap-5352XxLR.js +0 -42
- package/dashboard/dist/assets/DashboardPage-CDv0TIOL.js +0 -19
- package/dashboard/dist/assets/DevicePage-BlfIHcZX.js +0 -1
- package/dashboard/dist/assets/DialogClose-CismfYwe.js +0 -1
- package/dashboard/dist/assets/DialogDescription-DWKp1yez.js +0 -1
- package/dashboard/dist/assets/LeaderboardPage-Bq3-VO7w.js +0 -2
- package/dashboard/dist/assets/LeaderboardProfileModal-DH0EEK6q.js +0 -72
- package/dashboard/dist/assets/LoginPage-D6b6DZU3.js +0 -1
- package/dashboard/dist/assets/PetPage-DfpBkuCa.js +0 -1
- package/dashboard/dist/assets/ResetPasswordPage-BnOCFkwe.js +0 -1
- package/dashboard/dist/assets/SettingsPage-B-iHGL4q.js +0 -1
- package/dashboard/dist/assets/SkillsPage-DtG2aV-q.js +0 -1
- package/dashboard/dist/assets/agent-logos-D0vYkEpX.js +0 -1
- package/dashboard/dist/assets/check-C3RPBZiS.js +0 -1
- package/dashboard/dist/assets/main-Dy8Y_qst.css +0 -1
- package/dashboard/dist/assets/main-w0hAaCsy.js +0 -1190
- package/dashboard/dist/assets/use-native-settings-CvcOSUhn.js +0 -1
package/src/lib/rollout.js
CHANGED
|
@@ -960,15 +960,26 @@ async function parseOpenclawIncremental({
|
|
|
960
960
|
const cb = typeof onProgress === "function" ? onProgress : null;
|
|
961
961
|
const files = Array.isArray(sessionFiles) ? sessionFiles : [];
|
|
962
962
|
const totalFiles = files.length;
|
|
963
|
-
const hourlyState = normalizeHourlyState(
|
|
963
|
+
const hourlyState = normalizeHourlyState(
|
|
964
|
+
cursors?.hourly ? structuredClone(cursors.hourly) : null,
|
|
965
|
+
);
|
|
964
966
|
const projectEnabled = typeof projectQueuePath === "string" && projectQueuePath.length > 0;
|
|
965
|
-
const projectState = projectEnabled
|
|
967
|
+
const projectState = projectEnabled
|
|
968
|
+
? normalizeProjectState(
|
|
969
|
+
cursors?.projectHourly ? structuredClone(cursors.projectHourly) : null,
|
|
970
|
+
)
|
|
971
|
+
: null;
|
|
966
972
|
const projectTouchedBuckets = projectEnabled ? new Set() : null;
|
|
967
973
|
const touchedBuckets = new Set();
|
|
968
974
|
const defaultSource = normalizeSourceInput(source) || "openclaw";
|
|
969
975
|
|
|
970
|
-
|
|
971
|
-
cursors.files
|
|
976
|
+
const stagedFiles =
|
|
977
|
+
cursors.files && typeof cursors.files === "object"
|
|
978
|
+
? { ...cursors.files }
|
|
979
|
+
: {};
|
|
980
|
+
const cursorKeys = new Map();
|
|
981
|
+
for (const existingKey of Object.keys(stagedFiles)) {
|
|
982
|
+
cursorKeys.set(openclawCursorKey(existingKey), existingKey);
|
|
972
983
|
}
|
|
973
984
|
|
|
974
985
|
for (let idx = 0; idx < files.length; idx++) {
|
|
@@ -979,32 +990,129 @@ async function parseOpenclawIncremental({
|
|
|
979
990
|
typeof entry === "string"
|
|
980
991
|
? defaultSource
|
|
981
992
|
: normalizeSourceInput(entry?.source) || defaultSource;
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
const
|
|
986
|
-
|
|
987
|
-
const
|
|
988
|
-
|
|
993
|
+
const key = openclawCursorKey(filePath);
|
|
994
|
+
const previousKey = cursorKeys.get(key);
|
|
995
|
+
const prev = previousKey ? stagedFiles[previousKey] : null;
|
|
996
|
+
const prevUsageEvents =
|
|
997
|
+
prev?.usageEvents && typeof prev.usageEvents === "object" ? prev.usageEvents : {};
|
|
998
|
+
const hasUsageEventCursor =
|
|
999
|
+
prev &&
|
|
1000
|
+
Object.prototype.hasOwnProperty.call(prev, "usageEvents") &&
|
|
1001
|
+
prev.usageEvents &&
|
|
1002
|
+
typeof prev.usageEvents === "object";
|
|
1003
|
+
const legacyCursor = prev && !hasUsageEventCursor;
|
|
1004
|
+
const previousOffset = Number(prev?.offset || 0);
|
|
1005
|
+
let accepted = null;
|
|
1006
|
+
let openedRegularFile = false;
|
|
1007
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
1008
|
+
const fileHandle = await fs.open(filePath, "r").catch(() => null);
|
|
1009
|
+
if (!fileHandle) break;
|
|
1010
|
+
try {
|
|
1011
|
+
const openedStat = await fileHandle.stat();
|
|
1012
|
+
if (!openedStat.isFile()) break;
|
|
1013
|
+
openedRegularFile = true;
|
|
1014
|
+
const fileEndOffset = openedStat.size;
|
|
1015
|
+
let prefixFingerprint = null;
|
|
1016
|
+
let prefixFingerprintState = null;
|
|
1017
|
+
const offsetBoundaryMatches =
|
|
1018
|
+
hasUsageEventCursor &&
|
|
1019
|
+
previousOffset <= fileEndOffset &&
|
|
1020
|
+
await openclawOffsetEndsAtLineBoundary(fileHandle, previousOffset);
|
|
1021
|
+
const parsedLegacyUpdatedAt = Date.parse(String(prev?.updatedAt || ""));
|
|
1022
|
+
const legacyAggregateAfterMs =
|
|
1023
|
+
legacyCursor
|
|
1024
|
+
? Number.isFinite(parsedLegacyUpdatedAt)
|
|
1025
|
+
? parsedLegacyUpdatedAt
|
|
1026
|
+
: Number.POSITIVE_INFINITY
|
|
1027
|
+
: null;
|
|
1028
|
+
if (
|
|
1029
|
+
hasUsageEventCursor &&
|
|
1030
|
+
offsetBoundaryMatches &&
|
|
1031
|
+
prev?.usageFingerprint
|
|
1032
|
+
) {
|
|
1033
|
+
const prefix = await parseOpenclawSessionFile({
|
|
1034
|
+
filePath,
|
|
1035
|
+
fileHandle,
|
|
1036
|
+
startOffset: 0,
|
|
1037
|
+
endOffsetLimit: previousOffset,
|
|
1038
|
+
previousUsageEvents: {},
|
|
1039
|
+
appendOnly: false,
|
|
1040
|
+
collectOnly: true,
|
|
1041
|
+
});
|
|
1042
|
+
prefixFingerprint = prefix.usageFingerprint;
|
|
1043
|
+
prefixFingerprintState = prefix.usageFingerprintState;
|
|
1044
|
+
}
|
|
1045
|
+
const appendOnly =
|
|
1046
|
+
hasUsageEventCursor &&
|
|
1047
|
+
previousOffset <= fileEndOffset &&
|
|
1048
|
+
offsetBoundaryMatches &&
|
|
1049
|
+
sameOpenclawUsageFingerprint(
|
|
1050
|
+
prefixFingerprint,
|
|
1051
|
+
prev.usageFingerprint,
|
|
1052
|
+
);
|
|
1053
|
+
const startOffset = appendOnly ? previousOffset : 0;
|
|
1054
|
+
const attemptHourly = { version: 3, buckets: {}, groupQueued: {} };
|
|
1055
|
+
const attemptTouched = new Set();
|
|
1056
|
+
const result = await parseOpenclawSessionFile({
|
|
1057
|
+
filePath,
|
|
1058
|
+
fileHandle,
|
|
1059
|
+
startOffset,
|
|
1060
|
+
endOffsetLimit: fileEndOffset,
|
|
1061
|
+
previousUsageEvents: prevUsageEvents,
|
|
1062
|
+
appendOnly,
|
|
1063
|
+
aggregateAfterMs: legacyAggregateAfterMs,
|
|
1064
|
+
usageFingerprintState: appendOnly ? prefixFingerprintState : null,
|
|
1065
|
+
hourlyState: attemptHourly,
|
|
1066
|
+
touchedBuckets: attemptTouched,
|
|
1067
|
+
source: fileSource,
|
|
1068
|
+
projectState: null,
|
|
1069
|
+
projectTouchedBuckets: null,
|
|
1070
|
+
});
|
|
1071
|
+
const closedStat = await fileHandle.stat();
|
|
1072
|
+
const pathStat = await fs.stat(filePath).catch(() => null);
|
|
1073
|
+
if (
|
|
1074
|
+
!sameOpenclawFileGeneration(openedStat, closedStat) ||
|
|
1075
|
+
!sameOpenclawFileGeneration(closedStat, pathStat)
|
|
1076
|
+
) {
|
|
1077
|
+
continue;
|
|
1078
|
+
}
|
|
1079
|
+
accepted = {
|
|
1080
|
+
inode: closedStat.ino || 0,
|
|
1081
|
+
result,
|
|
1082
|
+
hourly: attemptHourly,
|
|
1083
|
+
touched: attemptTouched,
|
|
1084
|
+
usageEvents: result.usageEvents,
|
|
1085
|
+
usageFingerprint: result.usageFingerprint,
|
|
1086
|
+
};
|
|
1087
|
+
break;
|
|
1088
|
+
} finally {
|
|
1089
|
+
await fileHandle.close().catch(() => {});
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
if (!accepted) {
|
|
1093
|
+
if (!openedRegularFile) continue;
|
|
1094
|
+
throw new Error(`OpenClaw session changed repeatedly while parsing: ${filePath}`);
|
|
1095
|
+
}
|
|
989
1096
|
|
|
990
|
-
|
|
991
|
-
filePath,
|
|
992
|
-
startOffset,
|
|
1097
|
+
mergeOpenclawAttemptBuckets(
|
|
993
1098
|
hourlyState,
|
|
994
1099
|
touchedBuckets,
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
inode,
|
|
1002
|
-
offset: result.endOffset,
|
|
1100
|
+
accepted.hourly,
|
|
1101
|
+
accepted.touched,
|
|
1102
|
+
);
|
|
1103
|
+
if (previousKey && previousKey !== key) delete stagedFiles[previousKey];
|
|
1104
|
+
stagedFiles[key] = {
|
|
1105
|
+
provider: "openclaw",
|
|
1106
|
+
inode: accepted.inode,
|
|
1107
|
+
offset: accepted.result.endOffset,
|
|
1108
|
+
usageFingerprint: accepted.usageFingerprint,
|
|
1003
1109
|
updatedAt: new Date().toISOString(),
|
|
1110
|
+
usageEvents: accepted.usageEvents,
|
|
1004
1111
|
};
|
|
1112
|
+
cursorKeys.set(key, key);
|
|
1005
1113
|
|
|
1006
1114
|
filesProcessed += 1;
|
|
1007
|
-
eventsAggregated += result.eventsAggregated;
|
|
1115
|
+
eventsAggregated += accepted.result.eventsAggregated;
|
|
1008
1116
|
|
|
1009
1117
|
if (cb) {
|
|
1010
1118
|
cb({
|
|
@@ -1022,6 +1130,7 @@ async function parseOpenclawIncremental({
|
|
|
1022
1130
|
const projectBucketsQueued = projectEnabled
|
|
1023
1131
|
? await enqueueTouchedProjectBuckets({ projectQueuePath, projectState, projectTouchedBuckets })
|
|
1024
1132
|
: 0;
|
|
1133
|
+
cursors.files = stagedFiles;
|
|
1025
1134
|
hourlyState.updatedAt = new Date().toISOString();
|
|
1026
1135
|
cursors.hourly = hourlyState;
|
|
1027
1136
|
if (projectState) {
|
|
@@ -1032,23 +1141,131 @@ async function parseOpenclawIncremental({
|
|
|
1032
1141
|
return { filesProcessed, eventsAggregated, bucketsQueued, projectBucketsQueued };
|
|
1033
1142
|
}
|
|
1034
1143
|
|
|
1144
|
+
function openclawCursorKey(filePath) {
|
|
1145
|
+
if (typeof filePath !== "string") return "";
|
|
1146
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
1147
|
+
const isWindowsPath =
|
|
1148
|
+
/^[a-zA-Z]:\//.test(normalized) || normalized.startsWith("//");
|
|
1149
|
+
return isWindowsPath ? normalized.toLowerCase() : filePath;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
function sameOpenclawFileGeneration(left, right) {
|
|
1153
|
+
if (!left || !right || !left.isFile?.() || !right.isFile?.()) return false;
|
|
1154
|
+
const leftInode = Number(left.ino || 0);
|
|
1155
|
+
const rightInode = Number(right.ino || 0);
|
|
1156
|
+
if (leftInode > 0 && rightInode > 0) {
|
|
1157
|
+
if (leftInode !== rightInode || Number(left.dev || 0) !== Number(right.dev || 0)) {
|
|
1158
|
+
return false;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
return (
|
|
1162
|
+
Number(left.size || 0) === Number(right.size || 0) &&
|
|
1163
|
+
Number(left.mtimeMs || 0) === Number(right.mtimeMs || 0) &&
|
|
1164
|
+
Number(left.ctimeMs || 0) === Number(right.ctimeMs || 0)
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
async function openclawOffsetEndsAtLineBoundary(fileHandle, offset) {
|
|
1169
|
+
const byteOffset = Math.max(0, Number(offset) || 0);
|
|
1170
|
+
if (byteOffset === 0) return true;
|
|
1171
|
+
const buffer = Buffer.allocUnsafe(1);
|
|
1172
|
+
const { bytesRead } = await fileHandle.read(buffer, 0, 1, byteOffset - 1);
|
|
1173
|
+
return bytesRead === 1 && (buffer[0] === 0x0a || buffer[0] === 0x0d);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
function sameOpenclawUsageFingerprint(left, right) {
|
|
1177
|
+
return (
|
|
1178
|
+
left?.version === 1 &&
|
|
1179
|
+
right?.version === 1 &&
|
|
1180
|
+
left.eventCount === right.eventCount &&
|
|
1181
|
+
left.digest === right.digest
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
function mergeOpenclawAttemptBuckets(
|
|
1186
|
+
hourlyState,
|
|
1187
|
+
touchedBuckets,
|
|
1188
|
+
attemptHourly,
|
|
1189
|
+
attemptTouched,
|
|
1190
|
+
) {
|
|
1191
|
+
for (const key of attemptTouched) {
|
|
1192
|
+
const parsed = parseBucketKey(key);
|
|
1193
|
+
const attemptBucket = attemptHourly.buckets[key];
|
|
1194
|
+
if (!parsed || !attemptBucket) continue;
|
|
1195
|
+
const bucket = getHourlyBucket(
|
|
1196
|
+
hourlyState,
|
|
1197
|
+
parsed.source,
|
|
1198
|
+
parsed.model,
|
|
1199
|
+
parsed.hourStart,
|
|
1200
|
+
);
|
|
1201
|
+
addTotals(bucket.totals, attemptBucket.totals);
|
|
1202
|
+
touchedBuckets.add(key);
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1035
1206
|
async function parseOpenclawSessionFile({
|
|
1036
1207
|
filePath,
|
|
1208
|
+
fileHandle,
|
|
1037
1209
|
startOffset,
|
|
1210
|
+
endOffsetLimit,
|
|
1211
|
+
previousUsageEvents,
|
|
1212
|
+
appendOnly,
|
|
1213
|
+
aggregateAfterMs,
|
|
1214
|
+
usageFingerprintState,
|
|
1215
|
+
collectOnly = false,
|
|
1038
1216
|
hourlyState,
|
|
1039
1217
|
touchedBuckets,
|
|
1040
1218
|
source,
|
|
1041
1219
|
projectState,
|
|
1042
1220
|
projectTouchedBuckets,
|
|
1043
1221
|
}) {
|
|
1044
|
-
const st = await fs.stat(filePath);
|
|
1045
|
-
const endOffset =
|
|
1046
|
-
|
|
1222
|
+
const st = fileHandle ? await fileHandle.stat() : await fs.stat(filePath);
|
|
1223
|
+
const endOffset =
|
|
1224
|
+
Number.isFinite(endOffsetLimit) && endOffsetLimit >= 0
|
|
1225
|
+
? Math.min(st.size, endOffsetLimit)
|
|
1226
|
+
: st.size;
|
|
1227
|
+
const priorCounts =
|
|
1228
|
+
previousUsageEvents && typeof previousUsageEvents === "object"
|
|
1229
|
+
? previousUsageEvents
|
|
1230
|
+
: {};
|
|
1231
|
+
let fingerprintEventCount =
|
|
1232
|
+
Number.isInteger(usageFingerprintState?.eventCount) &&
|
|
1233
|
+
usageFingerprintState.eventCount >= 0
|
|
1234
|
+
? usageFingerprintState.eventCount
|
|
1235
|
+
: 0;
|
|
1236
|
+
const fingerprintHash =
|
|
1237
|
+
typeof usageFingerprintState?.hash?.copy === "function"
|
|
1238
|
+
? usageFingerprintState.hash.copy()
|
|
1239
|
+
: crypto.createHash("sha256");
|
|
1240
|
+
if (startOffset >= endOffset) {
|
|
1241
|
+
return {
|
|
1242
|
+
endOffset,
|
|
1243
|
+
eventsAggregated: 0,
|
|
1244
|
+
usageEvents: { ...priorCounts },
|
|
1245
|
+
usageFingerprint: {
|
|
1246
|
+
version: 1,
|
|
1247
|
+
eventCount: fingerprintEventCount,
|
|
1248
|
+
digest: fingerprintHash.copy().digest("hex"),
|
|
1249
|
+
},
|
|
1250
|
+
usageFingerprintState: {
|
|
1251
|
+
eventCount: fingerprintEventCount,
|
|
1252
|
+
hash: fingerprintHash,
|
|
1253
|
+
},
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1047
1256
|
|
|
1048
|
-
const stream = fssync.createReadStream(filePath, {
|
|
1257
|
+
const stream = fssync.createReadStream(filePath, {
|
|
1258
|
+
fd: fileHandle?.fd,
|
|
1259
|
+
autoClose: !fileHandle,
|
|
1260
|
+
encoding: "utf8",
|
|
1261
|
+
start: startOffset,
|
|
1262
|
+
end: endOffset - 1,
|
|
1263
|
+
});
|
|
1049
1264
|
const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
1050
1265
|
|
|
1051
1266
|
let eventsAggregated = 0;
|
|
1267
|
+
const scanCounts = appendOnly ? { ...priorCounts } : {};
|
|
1268
|
+
const usageEvents = { ...priorCounts };
|
|
1052
1269
|
for await (const line of rl) {
|
|
1053
1270
|
if (!line) continue;
|
|
1054
1271
|
// Fast-path filter: OpenClaw assistant messages include message.usage.totalTokens.
|
|
@@ -1065,13 +1282,26 @@ async function parseOpenclawSessionFile({
|
|
|
1065
1282
|
const msg = obj?.message;
|
|
1066
1283
|
if (!msg || typeof msg !== "object") continue;
|
|
1067
1284
|
|
|
1068
|
-
const usage = msg.usage;
|
|
1069
|
-
if (!usage
|
|
1285
|
+
const usage = normalizeOpenclawUsage(msg.usage);
|
|
1286
|
+
if (!usage) continue;
|
|
1070
1287
|
|
|
1071
1288
|
const tokenTimestamp = typeof obj?.timestamp === "string" ? obj.timestamp : null;
|
|
1072
1289
|
if (!tokenTimestamp) continue;
|
|
1073
1290
|
|
|
1074
1291
|
const model = normalizeModelInput(msg.model) || DEFAULT_MODEL;
|
|
1292
|
+
const eventIdentity = openclawUsageEventIdentity(obj, msg, usage, model);
|
|
1293
|
+
fingerprintHash.update(
|
|
1294
|
+
`${JSON.stringify(
|
|
1295
|
+
openclawUsageFingerprintMetadata(
|
|
1296
|
+
obj,
|
|
1297
|
+
msg,
|
|
1298
|
+
usage,
|
|
1299
|
+
model,
|
|
1300
|
+
eventIdentity.key,
|
|
1301
|
+
),
|
|
1302
|
+
)}\n`,
|
|
1303
|
+
);
|
|
1304
|
+
fingerprintEventCount += 1;
|
|
1075
1305
|
|
|
1076
1306
|
// OpenClaw wraps Codex, so it follows the same OpenAI convention where
|
|
1077
1307
|
// `input` INCLUDES cached reads. Normalize by subtracting cached from
|
|
@@ -1098,18 +1328,138 @@ async function parseOpenclawSessionFile({
|
|
|
1098
1328
|
const bucketStart = toUtcHalfHourStart(tokenTimestamp);
|
|
1099
1329
|
if (!bucketStart) continue;
|
|
1100
1330
|
|
|
1101
|
-
const
|
|
1102
|
-
|
|
1103
|
-
|
|
1331
|
+
const priorCount = Number(priorCounts[eventIdentity.key] || 0);
|
|
1332
|
+
const nextCount = Number(scanCounts[eventIdentity.key] || 0) + 1;
|
|
1333
|
+
scanCounts[eventIdentity.key] = nextCount;
|
|
1334
|
+
usageEvents[eventIdentity.key] = eventIdentity.unique
|
|
1335
|
+
? 1
|
|
1336
|
+
: Math.max(Number(usageEvents[eventIdentity.key] || 0), nextCount);
|
|
1337
|
+
if (
|
|
1338
|
+
eventIdentity.unique
|
|
1339
|
+
? priorCount > 0 || nextCount > 1
|
|
1340
|
+
: nextCount <= priorCount
|
|
1341
|
+
) {
|
|
1342
|
+
continue;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
if (
|
|
1346
|
+
aggregateAfterMs != null &&
|
|
1347
|
+
Date.parse(tokenTimestamp) <= aggregateAfterMs
|
|
1348
|
+
) {
|
|
1349
|
+
continue;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
if (!collectOnly) {
|
|
1353
|
+
const bucket = getHourlyBucket(hourlyState, source, model, bucketStart);
|
|
1354
|
+
addTotals(bucket.totals, delta);
|
|
1355
|
+
touchedBuckets.add(bucketKey(source, model, bucketStart));
|
|
1356
|
+
}
|
|
1104
1357
|
|
|
1105
1358
|
// Project-level OpenClaw attribution is not supported yet (no stable cwd info).
|
|
1106
1359
|
// If OpenClaw later records cwd per event, we can mirror rollout's project logic.
|
|
1107
|
-
eventsAggregated += 1;
|
|
1360
|
+
if (!collectOnly) eventsAggregated += 1;
|
|
1108
1361
|
}
|
|
1109
1362
|
|
|
1110
1363
|
rl.close();
|
|
1111
|
-
stream.close?.();
|
|
1112
|
-
return {
|
|
1364
|
+
if (!fileHandle) stream.close?.();
|
|
1365
|
+
return {
|
|
1366
|
+
endOffset,
|
|
1367
|
+
eventsAggregated,
|
|
1368
|
+
usageEvents,
|
|
1369
|
+
usageFingerprint: {
|
|
1370
|
+
version: 1,
|
|
1371
|
+
eventCount: fingerprintEventCount,
|
|
1372
|
+
digest: fingerprintHash.copy().digest("hex"),
|
|
1373
|
+
},
|
|
1374
|
+
usageFingerprintState: {
|
|
1375
|
+
eventCount: fingerprintEventCount,
|
|
1376
|
+
hash: fingerprintHash,
|
|
1377
|
+
},
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
function normalizeOpenclawUsage(usage) {
|
|
1382
|
+
if (!usage || typeof usage !== "object") return null;
|
|
1383
|
+
const normalized = {};
|
|
1384
|
+
for (const field of [
|
|
1385
|
+
"input",
|
|
1386
|
+
"cacheRead",
|
|
1387
|
+
"cacheWrite",
|
|
1388
|
+
"output",
|
|
1389
|
+
"totalTokens",
|
|
1390
|
+
]) {
|
|
1391
|
+
const rawValue = usage[field];
|
|
1392
|
+
if (rawValue === undefined) {
|
|
1393
|
+
normalized[field] = 0;
|
|
1394
|
+
continue;
|
|
1395
|
+
}
|
|
1396
|
+
if (
|
|
1397
|
+
typeof rawValue !== "number" ||
|
|
1398
|
+
!Number.isSafeInteger(rawValue) ||
|
|
1399
|
+
rawValue < 0
|
|
1400
|
+
) {
|
|
1401
|
+
return null;
|
|
1402
|
+
}
|
|
1403
|
+
normalized[field] = rawValue;
|
|
1404
|
+
}
|
|
1405
|
+
return normalized;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
function openclawUsageFingerprintMetadata(
|
|
1409
|
+
obj,
|
|
1410
|
+
msg,
|
|
1411
|
+
usage,
|
|
1412
|
+
model,
|
|
1413
|
+
identityKey,
|
|
1414
|
+
) {
|
|
1415
|
+
return {
|
|
1416
|
+
identityKey,
|
|
1417
|
+
timestamp: typeof obj?.timestamp === "string" ? obj.timestamp : null,
|
|
1418
|
+
messageTimestamp:
|
|
1419
|
+
typeof msg?.timestamp === "number" || typeof msg?.timestamp === "string"
|
|
1420
|
+
? msg.timestamp
|
|
1421
|
+
: null,
|
|
1422
|
+
responseId: typeof msg?.responseId === "string" ? msg.responseId : null,
|
|
1423
|
+
model,
|
|
1424
|
+
provider: typeof msg?.provider === "string" ? msg.provider : null,
|
|
1425
|
+
api: typeof msg?.api === "string" ? msg.api : null,
|
|
1426
|
+
input: Number(usage?.input || 0),
|
|
1427
|
+
cacheRead: Number(usage?.cacheRead || 0),
|
|
1428
|
+
cacheWrite: Number(usage?.cacheWrite || 0),
|
|
1429
|
+
output: Number(usage?.output || 0),
|
|
1430
|
+
totalTokens: Number(usage?.totalTokens || 0),
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
function openclawUsageEventIdentity(obj, msg, usage, model) {
|
|
1435
|
+
const stableId =
|
|
1436
|
+
typeof obj?.id === "string" && obj.id.trim() ? obj.id.trim() : null;
|
|
1437
|
+
if (stableId) {
|
|
1438
|
+
return {
|
|
1439
|
+
key: `id:${crypto.createHash("sha256").update(stableId).digest("hex")}`,
|
|
1440
|
+
unique: true,
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
const metadata = {
|
|
1445
|
+
timestamp: typeof obj?.timestamp === "string" ? obj.timestamp : null,
|
|
1446
|
+
messageTimestamp: typeof msg?.timestamp === "number" || typeof msg?.timestamp === "string"
|
|
1447
|
+
? msg.timestamp
|
|
1448
|
+
: null,
|
|
1449
|
+
responseId: typeof msg?.responseId === "string" ? msg.responseId : null,
|
|
1450
|
+
model,
|
|
1451
|
+
provider: typeof msg?.provider === "string" ? msg.provider : null,
|
|
1452
|
+
api: typeof msg?.api === "string" ? msg.api : null,
|
|
1453
|
+
input: Number(usage?.input || 0),
|
|
1454
|
+
cacheRead: Number(usage?.cacheRead || 0),
|
|
1455
|
+
cacheWrite: Number(usage?.cacheWrite || 0),
|
|
1456
|
+
output: Number(usage?.output || 0),
|
|
1457
|
+
totalTokens: Number(usage?.totalTokens || 0),
|
|
1458
|
+
};
|
|
1459
|
+
return {
|
|
1460
|
+
key: `meta:${crypto.createHash("sha256").update(JSON.stringify(metadata)).digest("hex")}`,
|
|
1461
|
+
unique: false,
|
|
1462
|
+
};
|
|
1113
1463
|
}
|
|
1114
1464
|
|
|
1115
1465
|
/**
|
|
@@ -12151,6 +12501,7 @@ module.exports = {
|
|
|
12151
12501
|
parseGeminiIncremental,
|
|
12152
12502
|
parseOpencodeIncremental,
|
|
12153
12503
|
parseOpencodeDbIncremental,
|
|
12504
|
+
openclawCursorKey,
|
|
12154
12505
|
parseOpenclawIncremental,
|
|
12155
12506
|
parseCursorApiIncremental,
|
|
12156
12507
|
parseKiroIncremental,
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import{c as ue,r as i,j as e,N as n,a2 as We,s as Fe,P as He,X as Ie,aH as Ge,Q as Oe}from"./main-w0hAaCsy.js";import{u as qe}from"./useCurrency-h3kqF52v.js";import{I as Ze}from"./info-C_BrDrcq.js";const Ke=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"m21 3-7 7",key:"1l2asr"}],["path",{d:"m3 21 7-7",key:"tjx5ai"}],["path",{d:"M9 21H3v-6",key:"wtvkvv"}]],Ve=ue("maximize-2",Ke);const Qe=[["rect",{x:"14",y:"3",width:"5",height:"18",rx:"1",key:"kaeet6"}],["rect",{x:"5",y:"3",width:"5",height:"18",rx:"1",key:"1wsw3u"}]],Je=ue("pause",Qe);const et=[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]],tt=ue("play",et);const at=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],rt=ue("rotate-ccw",at);const ot=[["path",{d:"M12 19h8",key:"baeox8"}],["path",{d:"m4 17 6-6-6-6",key:"1yngyt"}]],nt=ue("terminal",ot),J={emerald:{light:["#ebedf0","#a7f3d0","#6ee7b7","#34d399","#10b981"],dark:["#2d333b","#065f46","#059669","#10b981","#34d399"],gridColor:{light:"rgba(16, 185, 129, 0.12)",dark:"rgba(52, 211, 153, 0.08)"}},ocean:{light:["#f1f5f9","#93c5fd","#60a5fa","#3b82f6","#1d4ed8"],dark:["#1e293b","#1e3a8a","#2563eb","#3b82f6","#60a5fa"],gridColor:{light:"rgba(59, 130, 246, 0.12)",dark:"rgba(96, 165, 250, 0.08)"}},neon:{light:["#faf5ff","#ebd5ff","#c084fc","#a855f7","#7e22ce"],dark:["#2e1065","#581c87","#8b5cf6","#a855f7","#c084fc"],gridColor:{light:"rgba(168, 85, 247, 0.12)",dark:"rgba(192, 132, 252, 0.08)"}},amber:{light:["#fffbeb","#fde68a","#f59e0b","#d97706","#b45309"],dark:["#451a03","#78350f","#b45309","#d97706","#f59e0b"],gridColor:{light:"rgba(245, 158, 11, 0.12)",dark:"rgba(245, 158, 11, 0.08)"}}};function st(l,x){const h=/^#([0-9a-f]{6})$/i.exec(l);if(!h)return l;const c=parseInt(h[1],16),M=c>>16&255,P=c>>8&255,$=c&255,S=E=>Math.max(0,Math.min(255,Math.round(E*x)));return`rgb(${S(M)}, ${S(P)}, ${S($)})`}function O(l,x,h,c,M){const P=Math.cos(c),$=Math.sin(c),S=l*P-x*$,E=l*$+x*P,L=h,_=Math.cos(M),m=Math.sin(M),N=S,ee=E*_-L*m,F=E*m+L*_;return{x:N,y:ee,z:F}}function lt(l,x,h,c,M){return O(l,x,h,c,M)}function Se(l,x){const h=Number(x).toLocaleString();if(l>=4){const c=Math.floor(Math.random()*3)+1;return n(`heatmap.3d.voxel.joke.${c}`,{value:h})}else return l===3?n("heatmap.3d.voxel.level3",{value:h}):l===2?n("heatmap.3d.voxel.level2",{value:h}):l===1?n("heatmap.3d.voxel.level1",{value:h}):n("heatmap.3d.voxel.level0")}function _e({weeks:l,palette:x="auto",isDark:h=!1,interactive:c=!1,autoRotateInit:M=!1,onResetViewRef:P=null}){const $=J[x]||(x==="auto"?J.emerald:null),S=$?h?$.dark:$.light:Array.isArray(x)?x:h?J.emerald.dark:J.emerald.light,E=$?h?$.gridColor.dark:$.gridColor.light:h?"rgba(255,255,255,0.06)":"rgba(0,0,0,0.06)",L=-.2,_=.88,[m,N]=i.useState({yaw:L,pitch:_}),[ee,F]=i.useState(M),[pe,A]=i.useState(1),j=c?13:10.5,he=i.useMemo(()=>{const t=[],r=l.length;if(r===0||!c)return[];for(let s=0;s<=7;s++){const o=(s-3.5)*j,d=O(-r/2*j,o,0,m.yaw,m.pitch),p=O(r/2*j,o,0,m.yaw,m.pitch);t.push({d:`M${d.x},${d.y} L${p.x},${p.y}`,key:`horiz-${s}`})}for(let s=0;s<=r;s+=4){const o=(s-r/2)*j,d=O(o,-3.5*j,0,m.yaw,m.pitch),p=O(o,3.5*j,0,m.yaw,m.pitch);t.push({d:`M${d.x},${d.y} L${p.x},${p.y}`,key:`vert-${s}`})}if(r%4!==0){const s=(r-r/2)*j,o=O(s,-3.5*j,0,m.yaw,m.pitch),d=O(s,3.5*j,0,m.yaw,m.pitch);t.push({d:`M${o.x},${o.y} L${d.x},${d.y}`,key:"vert-last"})}return t},[l.length,m,j,c]);i.useEffect(()=>{P&&(P.current={reset:()=>{N({yaw:L,pitch:_}),F(!1),A(1),ye()},toggleAutoRotate:t=>{F(t)}})},[P]);const q=i.useRef(null),H=i.useRef(null),W=i.useRef(!1),ie=i.useRef({x:0,y:0}),Z=i.useRef({yaw:L,pitch:_}),Y=i.useRef({x:0,y:0}),re=i.useRef({x:0,y:0,time:0}),oe=i.useRef(null),[fe,ge]=i.useState(0),K=i.useRef(null),ne=i.useRef(!0);i.useEffect(()=>(ne.current=!0,()=>{ne.current=!1}),[]);const ye=()=>{K.current&&cancelAnimationFrame(K.current),ge(0);const t=performance.now(),r=1200,s=o=>{if(!ne.current)return;const d=o-t,p=Math.min(1,d/r),k=1-Math.pow(1-p,3);ge(k),p<1?K.current=requestAnimationFrame(s):K.current=null};K.current=requestAnimationFrame(s)};i.useEffect(()=>(ye(),()=>{K.current&&cancelAnimationFrame(K.current)}),[c]),i.useEffect(()=>{if(!ee||W.current||typeof window>"u"||typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches)return;let r;const s=()=>{if(typeof document<"u"&&document.visibilityState==="hidden"){r=requestAnimationFrame(s);return}N(o=>({yaw:o.yaw+.002,pitch:o.pitch})),r=requestAnimationFrame(s)};return r=requestAnimationFrame(s),()=>cancelAnimationFrame(r)},[ee]);const ce=(t,r)=>{c&&(W.current=!0,ie.current={x:t,y:r},Z.current={yaw:m.yaw,pitch:m.pitch},Y.current={x:0,y:0},re.current={x:t,y:r,time:performance.now()},oe.current&&cancelAnimationFrame(oe.current))},U=(t,r)=>{if(!W.current)return;const s=t-ie.current.x,o=r-ie.current.y,d=performance.now(),p=d-re.current.time;p>0&&(Y.current={x:(t-re.current.x)/p,y:(r-re.current.y)/p}),re.current={x:t,y:r,time:d};const k=.005,f=Z.current.yaw-s*k,g=Math.PI/2.3,D=Math.max(-g,Math.min(g,Z.current.pitch-o*k));N({yaw:f,pitch:D})},be=()=>{if(!W.current)return;W.current=!1;let t=-Y.current.x*12,r=-Y.current.y*12;const s=.95,o=()=>{W.current||(t*=s,r*=s,!(Math.abs(t)<.01&&Math.abs(r)<.01)&&(N(d=>{const p=d.yaw+t*.005,k=Math.PI/2.3,f=Math.max(-k,Math.min(k,d.pitch+r*.005));return{yaw:p,pitch:f}}),oe.current=requestAnimationFrame(o)))};oe.current=requestAnimationFrame(o)},[b,de]=i.useState(null),[V,xe]=i.useState({x:0,y:0,shiftX:0}),y=i.useRef(null);i.useEffect(()=>()=>{y.current&&clearTimeout(y.current)},[]),i.useEffect(()=>{if(!c||!H.current)return;const t=s=>{s.preventDefault();const o=-s.deltaY*.0025;A(d=>{const p=d+o;return Math.max(.5,Math.min(3,p))})},r=H.current;return r.addEventListener("wheel",t,{passive:!1}),()=>{r.removeEventListener("wheel",t)}},[c]);const C=i.useMemo(()=>{const t=[];return l.forEach((r,s)=>{(Array.isArray(r)?r:[]).forEach((o,d)=>{o&&t.push({key:o.day||`${s}-${d}`,col:s,row:d,level:o.level||0,value:o.value||0,day:o.day,models:o.models||null})})}),t},[l]),ve=j-(c?1.8:1.5),ke=c?38:28,Q=t=>Math.max(1.8,Number(t)/4*ke),te=i.useMemo(()=>{if(C.length===0)return[];const t=l.length;return C.map(r=>{const s=Q(r.level),o=Math.sqrt(Math.pow(r.col-t/2,2)+Math.pow(r.row-3.5,2)),d=Math.sqrt(Math.pow(t/2,2)+Math.pow(3.5,2)),p=o/d*.4,k=Math.min(1,Math.max(0,(fe-p)*(1/.6))),f=s*k,g=(r.col-t/2)*j,D=(r.row-3.5)*j,w=ve/2,G=[{x:g-w,y:D-w,z:0},{x:g+w,y:D-w,z:0},{x:g+w,y:D+w,z:0},{x:g-w,y:D+w,z:0},{x:g-w,y:D-w,z:f},{x:g+w,y:D-w,z:f},{x:g+w,y:D+w,z:f},{x:g-w,y:D+w,z:f}].map(B=>O(B.x,B.y,B.z,m.yaw,m.pitch)),me=O(g,D,f/2,m.yaw,m.pitch),Le=[{name:"top",indices:[4,5,6,7],scale:1,normal:[0,0,1]},{name:"bottom",indices:[3,2,1,0],scale:.4,normal:[0,0,-1]},{name:"left",indices:[3,0,4,7],scale:.55,normal:[-1,0,0]},{name:"right",indices:[1,2,6,5],scale:.75,normal:[1,0,0]},{name:"front",indices:[0,1,5,4],scale:.85,normal:[0,-1,0]},{name:"back",indices:[2,3,7,6],scale:.65,normal:[0,1,0]}],Re=S[Math.min(4,Math.max(0,Number(r.level)||0))],Ne=[],Ae=.35,De=-.4,Pe=.83;return Le.forEach(B=>{const we=lt(B.normal[0],B.normal[1],B.normal[2],m.yaw,m.pitch);if(we.z>.001){const Ce=G[B.indices[0]],ze=G[B.indices[1]],Me=G[B.indices[2]],Te=G[B.indices[3]],Ye=`M${Ce.x},${Ce.y} L${ze.x},${ze.y} L${Me.x},${Me.y} L${Te.x},${Te.y} Z`,Ue=we.x*Ae+we.y*De+we.z*Pe,Xe=h?.18:0,Be=B.scale*(.82+.28*Math.max(0,Ue))+Xe;Ne.push({name:B.name,d:Ye,fill:st(Re,Be)})}}),{...r,centerProj:me,renderedFaces:Ne}})},[C,m,S,l.length,fe,j,ve,ke]),se=i.useMemo(()=>[...te].sort((t,r)=>t.centerProj.z-r.centerProj.z),[te]),T=i.useMemo(()=>{if(se.length===0)return{minX:-100,minY:-100,maxX:100,maxY:100};let t=1/0,r=1/0,s=-1/0,o=-1/0;return se.forEach(d=>{const p=j*2,k=d.centerProj.x,f=d.centerProj.y;k-p<t&&(t=k-p),k+p>s&&(s=k+p),f-p<r&&(r=f-p),f+p>o&&(o=f+p)}),{minX:t,minY:r,maxX:s,maxY:o}},[se,j]),R=12,a=T.maxX-T.minX+R*2,u=T.maxY-T.minY+R*2,z=a/pe,v=u/pe,X=T.minX-R+(a-z)/2,I=T.minY-R+(u-v)/2,le=`${X} ${I} ${z} ${v}`;return C.length===0?e.jsx("div",{className:"py-8 text-center text-sm text-oai-gray-500",children:n("heatmap.empty")}):e.jsxs("div",{ref:H,className:`relative select-none outline-none ${c?"cursor-grab active:cursor-grabbing w-full h-full flex items-center justify-center":"w-full overflow-hidden flex justify-center"}`,onMouseDown:t=>{if(!c)return;ce(t.clientX,t.clientY);const r=o=>U(o.clientX,o.clientY),s=()=>{be(),window.removeEventListener("mousemove",r),window.removeEventListener("mouseup",s)};window.addEventListener("mousemove",r),window.addEventListener("mouseup",s)},onTouchStart:t=>{!c||t.touches.length===0||ce(t.touches[0].clientX,t.touches[0].clientY)},onTouchMove:t=>{!c||t.touches.length===0||U(t.touches[0].clientX,t.touches[0].clientY)},onTouchEnd:()=>{c&&be()},children:[e.jsxs("svg",{ref:q,viewBox:le,width:c?"95%":"100%",height:c?"95%":"auto",role:"img","aria-label":n("heatmap.iso.aria")||"3D interactive activity heatmap",style:{display:"block",width:"100%",height:"auto",maxWidth:c?"none":`${a}px`,maxHeight:c?"78vh":"none"},className:"transition-transform duration-300 ease-out",children:[c&&he.map(t=>e.jsx("path",{d:t.d,fill:"none",stroke:E,strokeWidth:.25,strokeDasharray:"1.5 2.5",strokeLinecap:"round"},t.key)),se.map(t=>{const r=b&&b.key===t.key;return e.jsxs("g",{onMouseEnter:s=>{if(y.current&&(clearTimeout(y.current),y.current=null),de(t),c&&q.current){const o=O((t.col-l.length/2)*j,(t.row-3.5)*j,Q(t.level),m.yaw,m.pitch);let d=0,p=0;const k=q.current;if(H.current&&typeof k.createSVGPoint=="function"&&typeof k.getScreenCTM=="function")try{const w=k.createSVGPoint();w.x=o.x,w.y=o.y;const ae=k.getScreenCTM();if(ae){const G=w.matrixTransform(ae),me=H.current.getBoundingClientRect();d=G.x-me.left,p=G.y-me.top}}catch{const ae=k.getBoundingClientRect(),G=T.maxX-T.minX+R*2,me=T.maxY-T.minY+R*2;d=(o.x-(T.minX-R))/G*ae.width,p=(o.y-(T.minY-R))/me*ae.height}else{const w=k.getBoundingClientRect(),ae=T.maxX-T.minX+R*2,G=T.maxY-T.minY+R*2;d=(o.x-(T.minX-R))/ae*w.width,p=(o.y-(T.minY-R))/G*w.height}const f=140;let g=0;const D=H.current?H.current.getBoundingClientRect().width:k.getBoundingClientRect().width;d<f?g=f-d:d>D-f&&(g=D-f-d),xe({x:d,y:p,shiftX:g})}},onMouseLeave:()=>{y.current&&clearTimeout(y.current),y.current=setTimeout(()=>{de(null)},150)},className:"transition-all duration-200",style:{filter:r?"brightness(1.15) drop-shadow(0 4px 6px rgba(0,0,0,0.15))":"none",cursor:c?"pointer":"default"},children:[!c&&t.day&&e.jsx("title",{children:`${t.day}: ${Number(t.value).toLocaleString()} tokens`}),t.renderedFaces.map((s,o)=>e.jsx("path",{d:s.d,fill:s.fill,stroke:s.fill,strokeWidth:.25,strokeLinejoin:"round"},o))]},t.key)})]}),c&&b&&e.jsxs("div",{onMouseEnter:()=>{y.current&&(clearTimeout(y.current),y.current=null)},onMouseLeave:()=>{y.current&&clearTimeout(y.current),y.current=setTimeout(()=>{de(null)},150)},className:"absolute z-[9999] w-0 h-0 transition-all duration-100 ease-out",style:{left:`${V.x}px`,top:`${V.y}px`},children:[e.jsxs("div",{className:"absolute left-0 bottom-[10px] backdrop-blur-md bg-white/90 dark:bg-oai-gray-900/90 border border-oai-gray-200/50 dark:border-oai-gray-800/50 shadow-xl rounded-xl p-3.5 max-w-[280px] min-w-[200px] flex flex-col gap-2 animate-in fade-in zoom-in-95 duration-100",style:{transform:`translateX(calc(-50% + ${V.shiftX}px))`},children:[e.jsxs("div",{className:"flex items-center justify-between border-b border-oai-gray-100 dark:border-oai-gray-800/80 pb-1.5",children:[e.jsx("span",{className:"text-[11px] font-semibold text-oai-gray-500 dark:text-oai-gray-400",children:b.day}),(()=>{const t=b.level===0?h?"#9ca3af":"#6b7280":S[b.level];return e.jsxs("span",{className:"text-[10px] px-2 py-0.5 rounded-full font-medium",style:{backgroundColor:t+"22",color:t,border:`1px solid ${t}44`},children:["Level ",b.level]})})()]}),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{className:"flex items-baseline gap-1",children:[e.jsx("span",{className:"text-lg font-bold text-oai-gray-900 dark:text-white leading-none",children:Number(b.value).toLocaleString()}),e.jsx("span",{className:"text-[10px] text-oai-gray-400 uppercase tracking-wider font-semibold",children:"Tokens"})]}),b.models&&Object.keys(b.models).length>0?e.jsxs("div",{className:"mt-1.5 border-t border-oai-gray-100 dark:border-oai-gray-800/60 pt-2 flex flex-col gap-1.5",children:[e.jsx("div",{className:"text-[10px] font-semibold text-oai-gray-400 dark:text-oai-gray-500 uppercase tracking-wider",children:"Model Breakdown"}),e.jsx("div",{className:"flex flex-col gap-2 max-h-[150px] overflow-y-auto pr-1.5 scrollbar-thin",children:Object.entries(b.models).map(([t,r])=>({name:t,val:Number(r)})).sort((t,r)=>r.val-t.val).map(({name:t,val:r})=>{const s=Number(b.value)||1,o=Math.round(r/s*100);return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex items-center justify-between text-[11px] gap-3",children:[e.jsx("span",{className:"font-medium text-oai-gray-750 dark:text-oai-gray-200 truncate max-w-[120px]",title:t,children:t}),e.jsxs("div",{className:"flex items-center gap-1.5 shrink-0",children:[e.jsx("span",{className:"font-mono text-oai-gray-900 dark:text-oai-gray-100 font-semibold",children:r.toLocaleString()}),e.jsxs("span",{className:"text-[9px] text-oai-gray-450 dark:text-oai-gray-500 min-w-[28px] text-right font-medium",children:[o,"%"]})]})]}),e.jsx("div",{className:"w-full h-1 bg-oai-gray-100 dark:bg-oai-gray-800/85 rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-300",style:{width:`${o}%`,backgroundColor:S[4],boxShadow:`0 0 4px ${S[4]}55`}})})]},t)})})]}):e.jsx("p",{className:"text-[11px] text-oai-gray-600 dark:text-oai-gray-300 leading-relaxed font-normal mt-1 border-t border-dashed border-oai-gray-100 dark:border-oai-gray-800/60 pt-1.5",children:Se(b.level,b.value)})]})]}),e.jsx("div",{className:"absolute bottom-[6px] left-0 -translate-x-1/2 w-2.5 h-2.5 rotate-45 bg-white dark:bg-oai-gray-900 border-r border-b border-oai-gray-200/50 dark:border-oai-gray-800/50 shadow-sm",style:{marginBottom:"1px"}})]})]})}const it=12,ct=3,dt=26,mt=["#ebedf0","#a7f3d0","#6ee7b7","#34d399","#10b981"],xt=["#30363d","#065f46","#059669","#10b981","#34d399"];function $e(l){const x=Number(l);return Number.isFinite(x)?x<1e3?x.toLocaleString():Oe(x,{decimals:2}):"0"}function ut(l){if(typeof l!="string")return null;const x=/^(\d{4})-(\d{2})-(\d{2})$/.exec(l.trim());if(!x)return null;const h=new Date(Date.UTC(Number(x[1]),Number(x[2])-1,Number(x[3])));return Number.isFinite(h.getTime())?h:null}function Ee(l,x){return new Date(Date.UTC(l.getUTCFullYear(),l.getUTCMonth(),l.getUTCDate()+x))}function pt(l,x){return Math.floor((Date.UTC(x.getUTCFullYear(),x.getUTCMonth(),x.getUTCDate())-Date.UTC(l.getUTCFullYear(),l.getUTCMonth(),l.getUTCDate()))/864e5)}function ht(l,x){const h=x==="mon"?1:0,c=l.getUTCDay();return Ee(l,-((c-h+7)%7))}function ft(l,x,h,c){if(!l)return[];const M=ut(x)||new Date,P=[];for(let _=11;_>=0;_-=1)P.push(new Date(Date.UTC(M.getUTCFullYear(),M.getUTCMonth()-_,1)));const $=ht(M,h),S=Ee($,-(l-1)*7),E=[],L=new Set;for(const _ of P){const m=Math.floor(pt(S,_)/7);m<0||m>=l||L.has(m)||(L.add(m),E.push({label:c[_.getUTCMonth()],index:m}))}return E}function vt({heatmap:l,timeZoneLabel:x,timeZoneShortLabel:h,hideLegend:c=!1,embedded:M=!1}){const{resolvedTheme:P}=We(),{currency:$,rate:S}=qe(),E=P==="dark",L=E?xt:mt,_=i.useRef(null),m=i.useRef(null),[N,ee]=i.useState(null),[F,pe]=i.useState({x:0,y:0,shiftX:0,flipY:!1}),A=i.useRef(null);i.useEffect(()=>()=>{A.current&&clearTimeout(A.current)},[]);const[j,he]=i.useState(!1),[q,H]=i.useState(!1),[W,ie]=i.useState(!1),Z=i.useRef(null),[Y,re]=i.useState("emerald"),oe=[n("heatmap.month.jan"),n("heatmap.month.feb"),n("heatmap.month.mar"),n("heatmap.month.apr"),n("heatmap.month.may"),n("heatmap.month.jun"),n("heatmap.month.jul"),n("heatmap.month.aug"),n("heatmap.month.sep"),n("heatmap.month.oct"),n("heatmap.month.nov"),n("heatmap.month.dec")],fe=(a,u)=>{if(!u||!u.day)return;A.current&&(clearTimeout(A.current),A.current=null),ee(u);const z=a.currentTarget.getBoundingClientRect(),v=typeof window<"u"?window.innerWidth:1024,X=z.left+z.width/2,I=z.top<300,le=I?z.bottom:z.top,t=140;let r=0;X<t?r=t-X:X>v-t&&(r=v-t-X),pe({x:X,y:le,shiftX:r,flipY:I})},ge=()=>{A.current&&clearTimeout(A.current),A.current=setTimeout(()=>{ee(null)},150)},K=()=>{H(!1),he(!0)},ne=()=>{H(!0)},ye=a=>{a.target===a.currentTarget&&q&&(he(!1),H(!1))};i.useEffect(()=>{if(!j||q)return;const a=u=>{u.key==="Escape"&&ne()};return window.addEventListener("keydown",a),()=>{window.removeEventListener("keydown",a)}},[j,q]);const ce=i.useMemo(()=>({emerald:{accentText:"text-emerald-500 dark:text-emerald-400",accentBg:"bg-emerald-500/10 dark:bg-emerald-400/10",accentBorder:"border-emerald-500/20 dark:border-emerald-400/15",hoverBorder:"hover:border-emerald-500/30 dark:hover:border-emerald-400/30",hoverGlow:"hover:shadow-[0_0_20px_-3px_rgba(16,185,129,0.15)] hover:dark:shadow-[0_0_20px_-3px_rgba(52,211,153,0.25)]",rawColor:"#10b981"},ocean:{accentText:"text-blue-500 dark:text-blue-400",accentBg:"bg-blue-500/10 dark:bg-blue-400/10",accentBorder:"border-blue-500/20 dark:border-blue-400/15",hoverBorder:"hover:border-blue-500/30 dark:hover:border-blue-400/30",hoverGlow:"hover:shadow-[0_0_20px_-3px_rgba(59,130,246,0.15)] hover:dark:shadow-[0_0_20px_-3px_rgba(96,165,250,0.25)]",rawColor:"#3b82f6"},neon:{accentText:"text-purple-500 dark:text-purple-400",accentBg:"bg-purple-500/10 dark:bg-purple-400/10",accentBorder:"border-purple-500/20 dark:border-purple-400/15",hoverBorder:"hover:border-purple-500/30 dark:hover:border-purple-400/30",hoverGlow:"hover:shadow-[0_0_20px_-3px_rgba(168,85,247,0.15)] hover:dark:shadow-[0_0_20px_-3px_rgba(192,132,252,0.25)]",rawColor:"#a855f7"},amber:{accentText:"text-amber-500 dark:text-amber-400",accentBg:"bg-amber-500/10 dark:bg-amber-400/10",accentBorder:"border-amber-500/20 dark:border-amber-400/15",hoverBorder:"hover:border-amber-500/30 dark:hover:border-amber-400/30",hoverGlow:"hover:shadow-[0_0_20px_-3px_rgba(245,158,11,0.15)] hover:dark:shadow-[0_0_20px_-3px_rgba(245,158,11,0.25)]",rawColor:"#f59e0b"}}),[]),U=ce[Y]||ce.emerald,be=J[Y]?E?J[Y].dark:J[Y].light:E?J.emerald.dark:J.emerald.light,[b,de]=i.useState(()=>{if(M)return"2d";try{return window.localStorage?.getItem("tt:heatmap-view")==="3d"?"3d":"2d"}catch{return"2d"}});i.useEffect(()=>{if(!M)try{window.localStorage?.setItem("tt:heatmap-view",b)}catch{}},[b,M]),i.useEffect(()=>{if(b!=="2d")return;const a=_.current;a&&(a.scrollLeft=a.scrollWidth)},[l?.weeks,b]),i.useEffect(()=>{const a=_.current;if(!a)return;const u=()=>{A.current&&(clearTimeout(A.current),A.current=null),ee(null)};return a.addEventListener("scroll",u),()=>a.removeEventListener("scroll",u)},[]);const V=l?.week_starts_on==="mon"?"mon":"sun",xe=i.useMemo(()=>{const a=Array.isArray(l?.weeks)?l.weeks:[];if(!a.length)return{weeks:[]};const u=[];for(const z of a)for(const v of Array.isArray(z)?z:[])v?.day&&u.push({day:v.day,total_tokens:v.total_tokens??v.value??0,billable_total_tokens:v.billable_total_tokens??v.value??v.total_tokens??0,models:v.models??null});return Fe({dailyRows:u,weeks:Math.max(52,a.length),to:l?.to,weekStartsOn:V})},[l?.to,l?.weeks,V]),y=xe?.weeks||[],C=i.useMemo(()=>{let a=0,u=0,z={day:"无数据",value:0},v=0,X=0;const I=[];y.forEach(f=>{(Array.isArray(f)?f:[]).forEach(g=>{g&&g.day&&I.push(g)})}),I.sort((f,g)=>f.day.localeCompare(g.day)),I.forEach(f=>{const g=Number(f.value)||0;a+=g,g>0?(u++,v++,v>X&&(X=v)):v=0,g>z.value&&(z={day:f.day,value:g})});const le=I.length||365,t=(u/le*100).toFixed(1);let r="heatmap.3d.modal.ai.eval.default",s="heatmap.3d.modal.ai.title.default";a>=15e6?(s="heatmap.3d.modal.ai.title.peak",r="heatmap.3d.modal.ai.eval.peak"):a>=5e6?(s="heatmap.3d.modal.ai.title.heavy",r="heatmap.3d.modal.ai.eval.heavy"):a>=1e6?(s="heatmap.3d.modal.ai.title.core",r="heatmap.3d.modal.ai.eval.core"):a>=2e4&&(s="heatmap.3d.modal.ai.title.steady",r="heatmap.3d.modal.ai.eval.steady");const o=l?.total_cost_usd,d=Number(o),k=o!=null&&(typeof o!="string"||o.trim()!=="")&&Number.isFinite(d)?d:a/15e5;return{totalTokens:a,activeDays:u,activeRate:t,maxSingleDay:z,maxStreak:X,aiEvaluationTitleKey:s,aiEvaluationKey:r,totalCostUsd:k}},[y,l?.total_cost_usd]),je=i.useMemo(()=>He(C.totalCostUsd,{currency:$,rate:S}),[C.totalCostUsd,$,S]),ve=V==="mon"?["Mon","Tue","Wed","Thu","Fri","Sat","Sun"].map(a=>n(`heatmap.day.${a.toLowerCase()}`)):["Sun","Mon","Tue","Wed","Thu","Fri","Sat"].map(a=>n(`heatmap.day.${a.toLowerCase()}`)),ke=i.useMemo(()=>ft(y.length,xe?.to,V,oe),[xe?.to,y.length,V,oe]);if(!y.length)return e.jsx("div",{className:"py-8 text-center text-sm text-oai-gray-500",children:n("heatmap.empty")});const Q=M?10:it,te=M?2:ct,se=M?22:dt,T=se+y.length*Q+Math.max(0,y.length-1)*te,R=`${se}px repeat(${y.length}, ${Q}px)`;return e.jsxs("div",{ref:m,className:M?"relative":"relative rounded-xl border border-oai-gray-200 dark:border-oai-gray-800 bg-white dark:bg-oai-gray-900 p-5",children:[!M&&e.jsxs("div",{className:"flex items-baseline justify-between mb-3",children:[e.jsx("h3",{className:"text-sm font-medium text-oai-gray-500 dark:text-oai-gray-300 uppercase tracking-wide",children:n("heatmap.title")}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("div",{role:"tablist","aria-label":"Heatmap view",className:"flex rounded-md border border-oai-gray-200 dark:border-oai-gray-800 p-0.5 text-[10px]",children:[e.jsx("button",{type:"button",role:"tab","aria-selected":b==="2d",onClick:()=>de("2d"),className:b==="2d"?"px-2 py-0.5 rounded bg-oai-gray-100 text-oai-black dark:bg-oai-gray-800 dark:text-oai-white font-medium":"px-2 py-0.5 rounded text-oai-gray-500 dark:text-oai-gray-400 hover:text-oai-gray-700 dark:hover:text-oai-gray-200",children:n("heatmap.view.2d")}),e.jsx("button",{type:"button",role:"tab","aria-selected":b==="3d",onClick:()=>de("3d"),className:b==="3d"?"px-2 py-0.5 rounded bg-oai-gray-100 text-oai-black dark:bg-oai-gray-800 dark:text-oai-white font-medium":"px-2 py-0.5 rounded text-oai-gray-500 dark:text-oai-gray-400 hover:text-oai-gray-700 dark:hover:text-oai-gray-200",children:n("heatmap.view.3d")})]}),e.jsx("span",{className:"text-xs text-oai-gray-400 dark:text-oai-gray-450",children:h||n("heatmap.legend.utc")})]})]}),b==="3d"&&e.jsxs("div",{onClick:K,className:"cursor-pointer group relative overflow-hidden rounded-lg hover:border-oai-gray-350 dark:hover:border-oai-gray-700 border border-transparent transition-all",title:n("heatmap.3d.hover_tip"),children:[e.jsx(_e,{weeks:y,isDark:E,palette:Y}),e.jsx("div",{className:"absolute inset-0 bg-gradient-to-t from-oai-gray-900/5 to-transparent pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity flex items-end justify-center pb-2",children:e.jsxs("span",{className:"text-[10px] bg-white/95 dark:bg-oai-gray-900/95 shadow border border-oai-gray-200/60 dark:border-oai-gray-800/80 px-2.5 py-1 rounded-full font-medium text-oai-gray-500 dark:text-oai-gray-400 flex items-center gap-1 transform translate-y-2 group-hover:translate-y-0 transition-transform duration-200",children:[e.jsx(Ve,{size:9}),n("heatmap.3d.hover_tip")]})})]}),b==="2d"&&e.jsx("div",{ref:_,className:"overflow-x-auto overflow-y-hidden heatmap-scroll-thin",children:e.jsxs("div",{style:{minWidth:T},children:[e.jsxs("div",{className:"grid text-[10px] uppercase text-oai-gray-400 dark:text-oai-gray-400 mb-1",style:{gridTemplateColumns:R,columnGap:te},children:[e.jsx("span",{}),ke.map(a=>e.jsx("span",{style:{gridColumnStart:a.index+2},className:"whitespace-nowrap",children:a.label},`${a.label}-${a.index}`))]}),e.jsxs("div",{className:"grid",style:{gridTemplateColumns:R,columnGap:te},children:[e.jsx("div",{className:"grid text-[10px] text-oai-gray-400 dark:text-oai-gray-400 sticky left-0 bg-white dark:bg-oai-gray-900 pr-2",style:{gridTemplateRows:`repeat(7, ${Q}px)`,rowGap:te},children:ve.map(a=>e.jsx("span",{className:"leading-none",children:a},a))}),e.jsx("div",{className:"grid",style:{gridAutoFlow:"column",gridTemplateRows:`repeat(7, ${Q}px)`,gap:te},children:y.map((a,u)=>(Array.isArray(a)?a:[]).map((z,v)=>{if(!z)return null;const X=z.day||`e-${u}-${v}`,I=Number(z.level)||0,le=L[I]||L[0];return e.jsx("span",{onMouseEnter:t=>fe(t,z),onMouseLeave:ge,className:"rounded-[2px] transition-transform hover:scale-125 hover:z-10 cursor-pointer",style:{width:Q,height:Q,background:le}},X)}))})]})]})}),!c&&e.jsxs("div",{className:"flex items-center justify-center gap-2 mt-3",children:[e.jsx("span",{className:"text-[10px] text-oai-gray-400 dark:text-oai-gray-400",children:n("heatmap.legend.less")}),e.jsx("div",{className:"flex gap-0.5",children:L.map((a,u)=>e.jsx("span",{className:"rounded-[1px]",style:{width:10,height:10,background:a}},u))}),e.jsx("span",{className:"text-[10px] text-oai-gray-400 dark:text-oai-gray-400",children:n("heatmap.legend.more")})]}),j&&e.jsx("div",{onAnimationEnd:ye,onClick:a=>{a.target===a.currentTarget&&ne()},className:`fixed inset-0 z-50 flex items-center justify-center p-3 md:p-6 backdrop-blur-md bg-black/15 dark:bg-black/40 ${q?"animate-tt-fade-out":"animate-tt-fade-in"}`,children:e.jsxs("div",{className:`relative w-full max-w-6xl h-[88vh] backdrop-blur-2xl bg-white/90 dark:bg-oai-gray-900/90 border border-oai-gray-200/50 dark:border-white/10 shadow-2xl rounded-2xl flex flex-col md:flex-row overflow-hidden ${q?"animate-tt-modal-exit":"animate-tt-modal"}`,children:[e.jsx("button",{type:"button",onClick:ne,className:"absolute top-4 right-4 z-50 p-2 rounded-full border border-oai-gray-200/60 dark:border-oai-gray-800/60 bg-white/50 dark:bg-oai-gray-900/50 text-oai-gray-500 dark:text-oai-gray-400 hover:text-oai-gray-900 dark:hover:text-white hover:rotate-90 hover:scale-105 active:scale-95 transition-all duration-300",children:e.jsx(Ie,{size:16})}),e.jsxs("div",{className:"w-full md:w-[340px] border-b md:border-b-0 md:border-r border-zinc-200/50 dark:border-zinc-800/40 p-5 md:p-6 flex flex-col gap-6 overflow-y-auto backdrop-blur-md bg-zinc-50/50 dark:bg-zinc-950/50",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-1.5 select-none",children:[e.jsxs("span",{className:"relative flex h-1.5 w-1.5",children:[e.jsx("span",{className:"animate-ping absolute inline-flex h-full w-full rounded-full opacity-75",style:{backgroundColor:U.rawColor}}),e.jsx("span",{className:"relative inline-flex rounded-full h-1.5 w-1.5",style:{backgroundColor:U.rawColor}})]}),e.jsx("span",{className:"text-[9px] font-extrabold uppercase tracking-widest font-mono text-zinc-400 dark:text-zinc-500",children:"3D Insight"})]}),e.jsx("h4",{className:"text-xl font-black text-zinc-900 dark:text-zinc-50 tracking-tight leading-none mt-2 select-none",children:n("heatmap.3d.modal.title")}),e.jsx("p",{className:"text-[11px] leading-relaxed text-zinc-400 dark:text-zinc-500 mt-2 font-normal select-none",children:n("heatmap.3d.modal.desc")})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-x-5 gap-y-5 border-y border-zinc-200/50 dark:border-zinc-800/50 py-5 select-none",children:[e.jsxs("div",{className:"flex flex-col gap-1 relative group cursor-help",children:[e.jsx("div",{className:"absolute left-0 bottom-full mb-2 pointer-events-none opacity-0 translate-y-1 group-hover:opacity-100 group-hover:translate-y-0 transition-all duration-200 z-50",children:e.jsxs("div",{className:"bg-white dark:bg-zinc-950 text-zinc-900 dark:text-zinc-50 text-[10px] font-semibold font-mono rounded-lg px-2.5 py-1.5 shadow-xl border border-zinc-200 dark:border-zinc-800/80 whitespace-nowrap flex flex-col",children:[e.jsx("span",{className:"text-[9px] text-zinc-400 dark:text-zinc-500",children:n("heatmap.3d.modal.stats.precision_total_tokens")}),e.jsxs("span",{className:"mt-0.5 font-bold text-zinc-900 dark:text-zinc-50",children:[C.totalTokens.toLocaleString()," Tokens"]})]})}),e.jsx("span",{className:"text-[9px] font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest font-mono",children:n("heatmap.3d.modal.stats.total_tokens")}),e.jsxs("div",{className:"flex items-baseline gap-1.5",children:[e.jsx("span",{className:"text-xl font-black text-zinc-900 dark:text-zinc-50 tracking-tight font-mono transition-transform duration-200 group-hover:-translate-y-[1px]",children:$e(C.totalTokens)}),e.jsx("div",{className:"opacity-30 group-hover:opacity-60 transition-opacity",children:e.jsx("svg",{width:"24",height:"10",viewBox:"0 0 24 10",fill:"none",children:e.jsx("path",{d:"M1 9C3 7 5 7 7 4C9 1 11 0 13 2C15 4 17 0 23 0",stroke:U.rawColor,strokeWidth:"1.2",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]}),e.jsxs("div",{className:"flex flex-col gap-1 group cursor-default",children:[e.jsx("span",{className:"text-[9px] font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest font-mono",children:n("heatmap.3d.modal.stats.estimated_cost")}),e.jsx("span",{className:"text-xl font-black text-zinc-900 dark:text-zinc-50 tracking-tight font-mono transition-transform duration-200 group-hover:-translate-y-[1px]",children:je})]}),e.jsxs("div",{className:"flex flex-col gap-1 group cursor-default",children:[e.jsx("span",{className:"text-[9px] font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest font-mono",children:n("heatmap.3d.modal.stats.active_rate_days")}),e.jsxs("span",{className:"text-xl font-black text-zinc-900 dark:text-zinc-50 tracking-tight font-mono transition-transform duration-200 group-hover:-translate-y-[1px]",children:[C.activeRate,"% ",e.jsxs("span",{className:"text-[10px] font-bold text-zinc-400 dark:text-zinc-500 font-mono",children:["(",C.activeDays,"D)"]})]})]}),e.jsxs("div",{className:"flex flex-col gap-1 group cursor-default",children:[e.jsx("span",{className:"text-[9px] font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest font-mono",children:n("heatmap.3d.modal.stats.max_streak")}),e.jsxs("span",{className:"text-xl font-black text-amber-500 tracking-tight font-mono transition-transform duration-200 group-hover:-translate-y-[1px]",children:[C.maxStreak," ",e.jsx("span",{className:"text-[10px] font-bold text-amber-500/80 font-mono",children:n("heatmap.3d.modal.stats.days_suffix")})]})]}),e.jsxs("div",{className:"flex flex-col gap-1 col-span-2 relative group cursor-help",children:[e.jsx("div",{className:"absolute left-0 bottom-full mb-2 pointer-events-none opacity-0 translate-y-1 group-hover:opacity-100 group-hover:translate-y-0 transition-all duration-200 z-50",children:e.jsxs("div",{className:"bg-white dark:bg-zinc-950 text-zinc-900 dark:text-zinc-50 text-[10px] font-semibold font-mono rounded-lg px-2.5 py-1.5 shadow-xl border border-zinc-200 dark:border-zinc-800/80 whitespace-nowrap flex flex-col",children:[e.jsx("span",{className:"text-[9px] text-zinc-400 dark:text-zinc-500",children:n("heatmap.3d.modal.stats.precision_peak_value")}),e.jsxs("span",{className:"mt-0.5 font-bold text-zinc-900 dark:text-zinc-50",children:[C.maxSingleDay.value>0?C.maxSingleDay.value.toLocaleString():n("heatmap.3d.modal.stats.no_data")," Tokens"]}),e.jsx("span",{className:"text-[8px] text-zinc-400 dark:text-zinc-500 mt-0.5",children:C.maxSingleDay.day!=="无数据"?C.maxSingleDay.day:n("heatmap.3d.modal.stats.no_data")})]})}),e.jsx("span",{className:"text-[9px] font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest font-mono",children:n("heatmap.3d.modal.stats.peak_day")}),e.jsxs("span",{className:"text-xl font-black text-zinc-900 dark:text-zinc-50 tracking-tight font-mono transition-transform duration-200 group-hover:-translate-y-[1px]",children:[C.maxSingleDay.value>0?$e(C.maxSingleDay.value):n("heatmap.3d.modal.stats.no_data")," ",e.jsxs("span",{className:"text-[10px] font-bold text-zinc-400 dark:text-zinc-500 font-mono",children:["(",C.maxSingleDay.day!=="无数据"?C.maxSingleDay.day:n("heatmap.3d.modal.stats.no_data"),")"]})]})]})]}),e.jsxs("div",{className:"flex flex-col gap-2.5 py-1",children:[e.jsxs("div",{className:"flex items-center gap-1.5 select-none",children:[e.jsx(nt,{size:11,style:{color:U.rawColor}}),e.jsx("span",{className:"text-[9px] font-extrabold uppercase tracking-widest font-mono",style:{color:U.rawColor},children:n(C.aiEvaluationTitleKey)})]}),e.jsxs("div",{className:"pl-3.5 border-l-2 relative transition-all duration-300 group",style:{borderColor:U.rawColor},children:[e.jsx("div",{className:"absolute inset-y-0 left-0 w-[3px] blur-[2px] opacity-15 pointer-events-none rounded-full",style:{backgroundColor:U.rawColor}}),e.jsx("p",{className:"text-[11px] leading-relaxed text-zinc-600 dark:text-zinc-400 font-normal",children:n(C.aiEvaluationKey)})]})]}),e.jsx("div",{className:"mt-auto border-t border-zinc-200/50 dark:border-zinc-800/50 pt-4 select-none",children:e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-[9px] font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest font-mono",children:n("heatmap.3d.modal.legend.title")}),e.jsx("span",{className:"text-[10px] font-medium text-zinc-500 dark:text-zinc-400",children:n(`heatmap.3d.modal.palette.${Y}`)})]}),e.jsx("div",{className:"flex gap-1",children:be.map((a,u)=>e.jsx("div",{className:"flex-1 h-1 rounded-[2px]",style:{backgroundColor:a},title:`Level ${u}`},u))})]})})]}),e.jsxs("div",{className:"flex-1 h-full relative flex items-center justify-center overflow-hidden p-4",children:[e.jsx("div",{className:"absolute top-1/4 left-1/3 w-96 h-96 rounded-full blur-[130px] pointer-events-none -translate-x-1/2 -translate-y-1/2 transition-all duration-500",style:{backgroundColor:U.rawColor+"15"}}),e.jsx("div",{className:"absolute bottom-1/4 right-1/3 w-80 h-80 rounded-full blur-[120px] pointer-events-none translate-x-1/2 translate-y-1/2 bg-purple-500/[0.04] dark:bg-purple-500/[0.08]"}),e.jsxs("div",{className:"absolute top-4 left-1/2 -translate-x-1/2 flex items-center gap-3 p-1.5 backdrop-blur-md bg-white/70 dark:bg-oai-gray-900/75 border border-oai-gray-200/60 dark:border-oai-gray-800/80 rounded-full shadow-lg z-30 select-none",children:[e.jsx("div",{className:"flex items-center gap-1.5 px-2",children:Object.keys(ce).map(a=>{const u=Y===a;return e.jsx("button",{type:"button",onClick:()=>re(a),title:n(`heatmap.3d.modal.palette.${a}`),className:`w-3.5 h-3.5 rounded-full transition-all duration-200 relative hover:scale-125 ${a==="emerald"?"bg-[#10b981]":a==="ocean"?"bg-[#3b82f6]":a==="neon"?"bg-[#a855f7]":"bg-[#f59e0b]"}`,children:u&&e.jsx("span",{className:"absolute inset-0 rounded-full ring-2 ring-offset-1 ring-offset-white dark:ring-offset-oai-gray-900 ring-oai-gray-900 dark:ring-white scale-110"})},a)})}),e.jsx("div",{className:"w-[1px] h-4 bg-oai-gray-200 dark:bg-oai-gray-800"}),e.jsxs("div",{className:"flex items-center gap-1 pr-1",children:[e.jsx("button",{type:"button",onClick:()=>{const a=!W;ie(a),Z.current&&Z.current.toggleAutoRotate(a)},title:W?n("heatmap.3d.modal.control.pause"):n("heatmap.3d.modal.control.play"),className:`p-1.5 rounded-full transition-all duration-200 hover:bg-oai-gray-100 dark:hover:bg-oai-gray-800 ${W?U.accentText:"text-oai-gray-400 hover:text-oai-gray-600 dark:hover:text-oai-gray-250"}`,children:W?e.jsx(Je,{size:12}):e.jsx(tt,{size:12})}),e.jsx("button",{type:"button",onClick:()=>{ie(!1),Z.current&&Z.current.reset()},title:n("heatmap.3d.modal.control.reset"),className:"p-1.5 rounded-full text-oai-gray-400 hover:text-oai-gray-600 dark:hover:text-oai-gray-250 hover:bg-oai-gray-100 dark:hover:bg-oai-gray-800 transition-all duration-200",children:e.jsx(rt,{size:12})})]})]}),e.jsx(_e,{weeks:y,isDark:E,interactive:!0,palette:Y,autoRotateInit:W,onResetViewRef:Z}),e.jsxs("div",{className:"absolute bottom-4 right-4 flex items-center gap-1.5 text-[9px] font-bold text-oai-gray-400 bg-white/80 dark:bg-oai-gray-900/80 border border-oai-gray-200/50 dark:border-oai-gray-800/80 rounded-md px-2.5 py-1.5 select-none pointer-events-none backdrop-blur-md shadow-sm",children:[e.jsx(Ze,{size:10,className:U.accentText}),e.jsx("span",{children:n("heatmap.3d.modal.footer.tip")})]})]})]})}),N&&!j&&typeof document<"u"&&Ge.createPortal(e.jsxs("div",{className:"fixed z-[9999] w-0 h-0 transition-all duration-100 ease-out pointer-events-none",style:{position:"fixed",left:`${F.x}px`,top:`${F.y}px`},children:[e.jsxs("div",{className:`absolute left-0 ${F.flipY?"top-[10px]":"bottom-[10px]"} backdrop-blur-md bg-white/95 dark:bg-oai-gray-900/95 border border-oai-gray-200/50 dark:border-oai-gray-800/50 shadow-xl rounded-xl p-3.5 max-w-[280px] min-w-[200px] flex flex-col gap-2 animate-in fade-in zoom-in-95 duration-100`,style:{transform:`translateX(calc(-50% + ${F.shiftX}px))`},children:[e.jsxs("div",{className:"flex items-center justify-between border-b border-oai-gray-100 dark:border-oai-gray-800/80 pb-1.5",children:[e.jsx("span",{className:"text-[11px] font-semibold text-oai-gray-500 dark:text-oai-gray-400",children:N.day}),(()=>{const a=N.level===0?E?"#9ca3af":"#6b7280":L[N.level];return e.jsxs("span",{className:"text-[10px] px-2 py-0.5 rounded-full font-medium",style:{backgroundColor:a+"22",color:a,border:`1px solid ${a}44`},children:["Level ",N.level]})})()]}),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{className:"flex items-baseline gap-1",children:[e.jsx("span",{className:"text-lg font-bold text-oai-gray-900 dark:text-white leading-none",children:Number(N.total_tokens??N.value).toLocaleString()}),e.jsx("span",{className:"text-[10px] text-oai-gray-400 uppercase tracking-wider font-semibold",children:"Tokens"})]}),N.models&&Object.keys(N.models).length>0?e.jsxs("div",{className:"mt-1.5 border-t border-oai-gray-100 dark:border-oai-gray-800/60 pt-2 flex flex-col gap-1.5",children:[e.jsx("div",{className:"text-[10px] font-semibold text-oai-gray-400 dark:text-oai-gray-500 uppercase tracking-wider",children:"Model Breakdown"}),e.jsx("div",{className:"flex flex-col gap-2 max-h-[150px] overflow-y-auto pr-1.5 oai-scrollbar",children:Object.entries(N.models).map(([a,u])=>({name:a,val:Number(u)})).sort((a,u)=>u.val-a.val).map(({name:a,val:u})=>{const z=Number(N.total_tokens??N.value)||1,v=Math.round(u/z*100);return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex items-center justify-between text-[11px] gap-3",children:[e.jsx("span",{className:"font-medium text-oai-gray-750 dark:text-oai-gray-200 truncate max-w-[120px]",title:a,children:a}),e.jsxs("div",{className:"flex items-center gap-1.5 shrink-0",children:[e.jsx("span",{className:"font-mono text-oai-gray-900 dark:text-oai-gray-100 font-semibold",children:u.toLocaleString()}),e.jsxs("span",{className:"text-[9px] text-oai-gray-450 dark:text-oai-gray-500 min-w-[28px] text-right font-medium",children:[v,"%"]})]})]}),e.jsx("div",{className:"w-full h-1 bg-oai-gray-100 dark:bg-oai-gray-800/85 rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-300",style:{width:`${v}%`,backgroundColor:L[4],boxShadow:`0 0 4px ${L[4]}55`}})})]},a)})})]}):e.jsx("p",{className:"text-[11px] text-oai-gray-600 dark:text-oai-gray-300 leading-relaxed font-normal mt-1 border-t border-dashed border-oai-gray-100 dark:border-oai-gray-800/60 pt-1.5",children:Se(N.level,N.total_tokens??N.value)})]})]}),e.jsx("div",{className:`absolute left-0 -translate-x-1/2 w-2.5 h-2.5 rotate-45 bg-white dark:bg-oai-gray-900 shadow-sm ${F.flipY?"top-[6px] border-l border-t":"bottom-[6px] border-r border-b"} border-oai-gray-200/50 dark:border-oai-gray-800/50`,style:F.flipY?{marginTop:"1px"}:{marginBottom:"1px"}})]}),document.body),e.jsx("style",{children:`
|
|
2
|
-
@keyframes tt-fade-in {
|
|
3
|
-
from { opacity: 0; }
|
|
4
|
-
to { opacity: 1; }
|
|
5
|
-
}
|
|
6
|
-
@keyframes tt-fade-out {
|
|
7
|
-
from { opacity: 1; }
|
|
8
|
-
to { opacity: 0; }
|
|
9
|
-
}
|
|
10
|
-
@keyframes tt-modal-entrance {
|
|
11
|
-
from {
|
|
12
|
-
opacity: 0;
|
|
13
|
-
transform: scale(0.96) translateY(10px);
|
|
14
|
-
}
|
|
15
|
-
to {
|
|
16
|
-
opacity: 1;
|
|
17
|
-
transform: scale(1) translateY(0);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
@keyframes tt-modal-exit {
|
|
21
|
-
from {
|
|
22
|
-
opacity: 1;
|
|
23
|
-
transform: scale(1) translateY(0);
|
|
24
|
-
}
|
|
25
|
-
to {
|
|
26
|
-
opacity: 0;
|
|
27
|
-
transform: scale(0.96) translateY(10px);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
.animate-tt-fade-in {
|
|
31
|
-
animation: tt-fade-in 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
32
|
-
}
|
|
33
|
-
.animate-tt-fade-out {
|
|
34
|
-
animation: tt-fade-out 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
35
|
-
}
|
|
36
|
-
.animate-tt-modal {
|
|
37
|
-
animation: tt-modal-entrance 0.3s cubic-bezier(0.34, 1.3, 0.64, 1) forwards;
|
|
38
|
-
}
|
|
39
|
-
.animate-tt-modal-exit {
|
|
40
|
-
animation: tt-modal-exit 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
41
|
-
}
|
|
42
|
-
`})]})}export{vt as A,Ve as M,nt as T};
|