token-usage-sync 1.5.1 → 1.5.2
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/index.js +68 -11
- package/lib/calculations.js +61 -6
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -25,7 +25,7 @@ const flags = {
|
|
|
25
25
|
|
|
26
26
|
// API URL(環境変数 or コマンドライン引数)
|
|
27
27
|
const API_URL = process.env.SYNC_API_URL || getArgValue('api-url');
|
|
28
|
-
const USER_ID = process.env.SYNC_USER_ID || getArgValue('user-id') || '
|
|
28
|
+
const USER_ID = process.env.SYNC_USER_ID || getArgValue('user-id') || 'msgmacbookair';
|
|
29
29
|
|
|
30
30
|
// ヘルプ表示
|
|
31
31
|
if (flags.help) {
|
|
@@ -125,12 +125,67 @@ function calculateUsageForPeriod(entries, hoursAgo) {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
// 重み付けトークン計算(Claude Code実測ベース)
|
|
128
|
-
// Cache Read
|
|
128
|
+
// Cache Read は 0.1x、Cache Create は 1.25x
|
|
129
129
|
const weightedTokens = Math.round(
|
|
130
130
|
inputTokens * 1.0 +
|
|
131
131
|
outputTokens * 1.0 +
|
|
132
|
-
cacheCreationTokens * 1.
|
|
133
|
-
cacheReadTokens * 0
|
|
132
|
+
cacheCreationTokens * 1.25 +
|
|
133
|
+
cacheReadTokens * 0.1
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
inputTokens,
|
|
138
|
+
outputTokens,
|
|
139
|
+
cacheCreationTokens,
|
|
140
|
+
cacheReadTokens,
|
|
141
|
+
totalTokens: inputTokens + outputTokens + cacheCreationTokens + cacheReadTokens,
|
|
142
|
+
weightedTokens,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const WEEKLY_RESET = { weekday: 6, hour: 8, minute: 59 }; // Saturday 08:59 (local time)
|
|
147
|
+
|
|
148
|
+
function getLastWeeklyReset(now = new Date()) {
|
|
149
|
+
const reset = new Date(now);
|
|
150
|
+
const day = reset.getDay();
|
|
151
|
+
const diff = (day - WEEKLY_RESET.weekday + 7) % 7;
|
|
152
|
+
reset.setDate(reset.getDate() - diff);
|
|
153
|
+
reset.setHours(WEEKLY_RESET.hour, WEEKLY_RESET.minute, 0, 0);
|
|
154
|
+
|
|
155
|
+
if (now < reset) {
|
|
156
|
+
reset.setDate(reset.getDate() - 7);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return reset;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function calculateUsageSince(entries, startTime, now = new Date()) {
|
|
163
|
+
let inputTokens = 0;
|
|
164
|
+
let outputTokens = 0;
|
|
165
|
+
let cacheCreationTokens = 0;
|
|
166
|
+
let cacheReadTokens = 0;
|
|
167
|
+
|
|
168
|
+
for (const entry of entries) {
|
|
169
|
+
const timestamp = entry.timestamp || entry.message?.timestamp;
|
|
170
|
+
if (!timestamp) continue;
|
|
171
|
+
|
|
172
|
+
const entryTime = new Date(timestamp);
|
|
173
|
+
if (entryTime < startTime || entryTime > now) continue;
|
|
174
|
+
|
|
175
|
+
const usage = entry.message?.usage || entry.usage;
|
|
176
|
+
if (!usage) continue;
|
|
177
|
+
|
|
178
|
+
inputTokens += usage.input_tokens || 0;
|
|
179
|
+
outputTokens += usage.output_tokens || 0;
|
|
180
|
+
cacheCreationTokens += usage.cache_creation_input_tokens || 0;
|
|
181
|
+
cacheReadTokens += usage.cache_read_input_tokens || 0;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const weightedTokens = Math.round(
|
|
185
|
+
inputTokens * 1.0 +
|
|
186
|
+
outputTokens * 1.0 +
|
|
187
|
+
cacheCreationTokens * 1.25 +
|
|
188
|
+
cacheReadTokens * 0.1
|
|
134
189
|
);
|
|
135
190
|
|
|
136
191
|
return {
|
|
@@ -225,8 +280,8 @@ function calculateActiveBlockUsage(entries, now = new Date()) {
|
|
|
225
280
|
const weightedTokens = Math.round(
|
|
226
281
|
inputTokens * 1.0 +
|
|
227
282
|
outputTokens * 1.0 +
|
|
228
|
-
cacheCreationTokens * 1.
|
|
229
|
-
cacheReadTokens * 0
|
|
283
|
+
cacheCreationTokens * 1.25 +
|
|
284
|
+
cacheReadTokens * 0.1
|
|
230
285
|
);
|
|
231
286
|
|
|
232
287
|
const elapsedMinutes = Math.round((nowTime - activeBlock.startTime) / 60000);
|
|
@@ -305,7 +360,7 @@ function aggregateUsage(entries) {
|
|
|
305
360
|
// ローリングウィンドウの使用量を計算
|
|
306
361
|
const last5Hours = calculateUsageForPeriod(entries, 5);
|
|
307
362
|
const last24Hours = calculateUsageForPeriod(entries, 24);
|
|
308
|
-
const lastWeek =
|
|
363
|
+
const lastWeek = calculateUsageSince(entries, getLastWeeklyReset());
|
|
309
364
|
|
|
310
365
|
return {
|
|
311
366
|
summary: {
|
|
@@ -416,9 +471,10 @@ async function main() {
|
|
|
416
471
|
console.log('\n📊 Claude Code Usage Summary\n');
|
|
417
472
|
|
|
418
473
|
// 制限値
|
|
419
|
-
const LIMIT_WEEK_RAW =
|
|
474
|
+
const LIMIT_WEEK_RAW = 180_000_000; // 週間制限: 180M raw tokens
|
|
420
475
|
|
|
421
|
-
const
|
|
476
|
+
const lastWeekWeighted = usage.limits.lastWeek.weightedTokens ?? usage.limits.lastWeek.totalTokens;
|
|
477
|
+
const pctWeek = Math.round((lastWeekWeighted / LIMIT_WEEK_RAW) * 100);
|
|
422
478
|
|
|
423
479
|
// アクティブブロック(Claude Code準拠のセッションブロック方式)
|
|
424
480
|
console.log('=== Active Session Block ===');
|
|
@@ -429,7 +485,8 @@ async function main() {
|
|
|
429
485
|
const remainingStr = `${Math.floor(remaining / 60)}h ${remaining % 60}m`;
|
|
430
486
|
|
|
431
487
|
console.log(`Status: ACTIVE (${elapsedStr} elapsed, ${remainingStr} remaining)`);
|
|
432
|
-
|
|
488
|
+
const activeBlockWeighted = usage.activeBlock.weightedTokens ?? usage.activeBlock.totalTokens;
|
|
489
|
+
console.log(`Tokens: ${activeBlockWeighted.toLocaleString()}`);
|
|
433
490
|
console.log(` Input: ${usage.activeBlock.inputTokens.toLocaleString()}`);
|
|
434
491
|
console.log(` Output: ${usage.activeBlock.outputTokens.toLocaleString()}`);
|
|
435
492
|
console.log(` Cache: ${usage.activeBlock.cacheCreationTokens.toLocaleString()} (create) + ${usage.activeBlock.cacheReadTokens.toLocaleString()} (read)`);
|
|
@@ -438,7 +495,7 @@ async function main() {
|
|
|
438
495
|
}
|
|
439
496
|
|
|
440
497
|
console.log('\n=== Weekly Limit ===');
|
|
441
|
-
console.log(`Weekly: ${
|
|
498
|
+
console.log(`Weekly: ${lastWeekWeighted.toLocaleString()} / ${LIMIT_WEEK_RAW.toLocaleString()} (${pctWeek}%)`);
|
|
442
499
|
|
|
443
500
|
console.log('\n=== All Time Total ===');
|
|
444
501
|
console.log(`Total Tokens: ${usage.summary.totalTokens.toLocaleString()}`);
|
package/lib/calculations.js
CHANGED
|
@@ -87,8 +87,8 @@ export function calculateActiveBlockUsage(entries, now = new Date()) {
|
|
|
87
87
|
const weightedTokens = Math.round(
|
|
88
88
|
inputTokens * 1.0 +
|
|
89
89
|
outputTokens * 1.0 +
|
|
90
|
-
cacheCreationTokens * 1.
|
|
91
|
-
cacheReadTokens * 0
|
|
90
|
+
cacheCreationTokens * 1.25 +
|
|
91
|
+
cacheReadTokens * 0.1
|
|
92
92
|
);
|
|
93
93
|
|
|
94
94
|
const elapsedMinutes = Math.round((nowTime - activeBlock.startTime) / 60000);
|
|
@@ -134,12 +134,67 @@ export function calculateUsageForPeriod(entries, hoursAgo, now = new Date()) {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
// 重み付けトークン計算(Claude Code実測ベース)
|
|
137
|
-
// Cache Read
|
|
137
|
+
// Cache Read は 0.1x、Cache Create は 1.25x
|
|
138
138
|
const weightedTokens = Math.round(
|
|
139
139
|
inputTokens * 1.0 +
|
|
140
140
|
outputTokens * 1.0 +
|
|
141
|
-
cacheCreationTokens * 1.
|
|
142
|
-
cacheReadTokens * 0
|
|
141
|
+
cacheCreationTokens * 1.25 +
|
|
142
|
+
cacheReadTokens * 0.1
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
inputTokens,
|
|
147
|
+
outputTokens,
|
|
148
|
+
cacheCreationTokens,
|
|
149
|
+
cacheReadTokens,
|
|
150
|
+
totalTokens: inputTokens + outputTokens + cacheCreationTokens + cacheReadTokens,
|
|
151
|
+
weightedTokens,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const WEEKLY_RESET = { weekday: 6, hour: 8, minute: 59 }; // Saturday 08:59 (local time)
|
|
156
|
+
|
|
157
|
+
function getLastWeeklyReset(now = new Date()) {
|
|
158
|
+
const reset = new Date(now);
|
|
159
|
+
const day = reset.getDay();
|
|
160
|
+
const diff = (day - WEEKLY_RESET.weekday + 7) % 7;
|
|
161
|
+
reset.setDate(reset.getDate() - diff);
|
|
162
|
+
reset.setHours(WEEKLY_RESET.hour, WEEKLY_RESET.minute, 0, 0);
|
|
163
|
+
|
|
164
|
+
if (now < reset) {
|
|
165
|
+
reset.setDate(reset.getDate() - 7);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return reset;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function calculateUsageSince(entries, startTime, now = new Date()) {
|
|
172
|
+
let inputTokens = 0;
|
|
173
|
+
let outputTokens = 0;
|
|
174
|
+
let cacheCreationTokens = 0;
|
|
175
|
+
let cacheReadTokens = 0;
|
|
176
|
+
|
|
177
|
+
for (const entry of entries) {
|
|
178
|
+
const timestamp = entry.timestamp || entry.message?.timestamp;
|
|
179
|
+
if (!timestamp) continue;
|
|
180
|
+
|
|
181
|
+
const entryTime = new Date(timestamp);
|
|
182
|
+
if (entryTime < startTime || entryTime > now) continue;
|
|
183
|
+
|
|
184
|
+
const usage = entry.message?.usage || entry.usage;
|
|
185
|
+
if (!usage) continue;
|
|
186
|
+
|
|
187
|
+
inputTokens += usage.input_tokens || 0;
|
|
188
|
+
outputTokens += usage.output_tokens || 0;
|
|
189
|
+
cacheCreationTokens += usage.cache_creation_input_tokens || 0;
|
|
190
|
+
cacheReadTokens += usage.cache_read_input_tokens || 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const weightedTokens = Math.round(
|
|
194
|
+
inputTokens * 1.0 +
|
|
195
|
+
outputTokens * 1.0 +
|
|
196
|
+
cacheCreationTokens * 1.25 +
|
|
197
|
+
cacheReadTokens * 0.1
|
|
143
198
|
);
|
|
144
199
|
|
|
145
200
|
return {
|
|
@@ -210,7 +265,7 @@ export function aggregateUsage(entries, now = new Date()) {
|
|
|
210
265
|
// ローリングウィンドウの使用量を計算(後方互換性)
|
|
211
266
|
const last5Hours = calculateUsageForPeriod(entries, 5, now);
|
|
212
267
|
const last24Hours = calculateUsageForPeriod(entries, 24, now);
|
|
213
|
-
const lastWeek =
|
|
268
|
+
const lastWeek = calculateUsageSince(entries, getLastWeeklyReset(now), now);
|
|
214
269
|
|
|
215
270
|
return {
|
|
216
271
|
summary: {
|