token-usage-sync 1.5.2 → 1.6.0

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.
@@ -0,0 +1,80 @@
1
+ export type Usage = {
2
+ input_tokens?: number;
3
+ output_tokens?: number;
4
+ cache_creation_input_tokens?: number;
5
+ cache_read_input_tokens?: number;
6
+ };
7
+ export type Entry = {
8
+ timestamp?: string;
9
+ requestId?: string;
10
+ message?: {
11
+ timestamp?: string;
12
+ model?: string;
13
+ usage?: Usage;
14
+ id?: string;
15
+ };
16
+ model?: string;
17
+ usage?: Usage;
18
+ };
19
+ export type EntryWithTimestamp = Entry & {
20
+ _ts: number;
21
+ };
22
+ export type SessionBlock = {
23
+ startTime: number;
24
+ endTime: number;
25
+ entries: EntryWithTimestamp[];
26
+ };
27
+ export type UsageResult = {
28
+ inputTokens: number;
29
+ outputTokens: number;
30
+ cacheCreationTokens: number;
31
+ cacheReadTokens: number;
32
+ totalTokens: number;
33
+ };
34
+ export type ActiveBlockResult = UsageResult & {
35
+ blockStartTime: Date | null;
36
+ blockEndTime: Date | null;
37
+ elapsedMinutes: number;
38
+ remainingMinutes: number;
39
+ };
40
+ export type ModelStats = {
41
+ inputTokens: number;
42
+ outputTokens: number;
43
+ cacheCreationTokens: number;
44
+ cacheReadTokens: number;
45
+ count: number;
46
+ };
47
+ export type DateStats = {
48
+ inputTokens: number;
49
+ outputTokens: number;
50
+ cacheCreationTokens: number;
51
+ cacheReadTokens: number;
52
+ count: number;
53
+ };
54
+ export type AggregatedUsage = {
55
+ summary: {
56
+ totalInputTokens: number;
57
+ totalOutputTokens: number;
58
+ totalTokens: number;
59
+ cacheCreationInputTokens: number;
60
+ cacheReadInputTokens: number;
61
+ messageCount: number;
62
+ };
63
+ activeBlock: ActiveBlockResult;
64
+ limits: {
65
+ last5Hours: UsageResult;
66
+ last24Hours: UsageResult;
67
+ lastWeek: UsageResult;
68
+ };
69
+ byModel: Record<string, ModelStats>;
70
+ byDate: Record<string, DateStats>;
71
+ };
72
+ export declare function identifySessionBlocks(entries: Entry[], sessionDurationHours?: number): SessionBlock[];
73
+ export declare function calculateActiveBlockUsage(entries: Entry[], now?: Date): ActiveBlockResult;
74
+ export declare function calculateUsageForPeriod(entries: Entry[], hoursAgo: number, now?: Date): UsageResult;
75
+ export declare function getLastWeeklyReset(now?: Date): Date;
76
+ export declare function getNextWeeklyReset(now?: Date): Date;
77
+ export declare function aggregateUsage(entries: Entry[], now?: Date): AggregatedUsage;
78
+ export declare function percent(used: number, limit: number): number;
79
+ export declare function formatTokens(n: number): string;
80
+ //# sourceMappingURL=calculations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calculations.d.ts","sourceRoot":"","sources":["../src/calculations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,304 @@
1
+ // requestIdで重複除去(最初のエントリを使用)
2
+ function deduplicateByRequestId(entries) {
3
+ const seen = new Set();
4
+ const result = [];
5
+ for (const entry of entries) {
6
+ const reqId = entry.requestId || entry.message?.id;
7
+ if (reqId) {
8
+ if (!seen.has(reqId)) {
9
+ seen.add(reqId);
10
+ result.push(entry);
11
+ }
12
+ }
13
+ else {
14
+ // requestIdがない場合はそのまま追加
15
+ result.push(entry);
16
+ }
17
+ }
18
+ return result;
19
+ }
20
+ // トークン合計計算(ccusage準拠)
21
+ // すべてのトークンを1.0倍で計算
22
+ function calculateTotalTokens(inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens) {
23
+ return inputTokens + outputTokens + cacheCreationTokens + cacheReadTokens;
24
+ }
25
+ // セッションブロックを特定する
26
+ // Claude Codeは5時間ブロック方式: セッション開始から5時間でリセット
27
+ export function identifySessionBlocks(entries, sessionDurationHours = 5) {
28
+ // タイムスタンプでソート
29
+ const sorted = entries
30
+ .filter((e) => !!(e.timestamp || e.message?.timestamp))
31
+ .map((e) => ({
32
+ ...e,
33
+ _ts: new Date(e.timestamp || e.message?.timestamp || '').getTime(),
34
+ }))
35
+ .sort((a, b) => a._ts - b._ts);
36
+ const blocks = [];
37
+ let currentBlock = null;
38
+ for (const entry of sorted) {
39
+ const entryTime = entry._ts;
40
+ if (!currentBlock) {
41
+ // 最初のブロック開始
42
+ currentBlock = {
43
+ startTime: entryTime,
44
+ endTime: entryTime + sessionDurationHours * 60 * 60 * 1000,
45
+ entries: [entry],
46
+ };
47
+ }
48
+ else if (entryTime <= currentBlock.endTime) {
49
+ // 現在のブロック内
50
+ currentBlock.entries.push(entry);
51
+ }
52
+ else {
53
+ // 新しいブロック開始
54
+ blocks.push(currentBlock);
55
+ currentBlock = {
56
+ startTime: entryTime,
57
+ endTime: entryTime + sessionDurationHours * 60 * 60 * 1000,
58
+ entries: [entry],
59
+ };
60
+ }
61
+ }
62
+ if (currentBlock) {
63
+ blocks.push(currentBlock);
64
+ }
65
+ return blocks;
66
+ }
67
+ // 現在のアクティブブロックの使用量を計算
68
+ export function calculateActiveBlockUsage(entries, now = new Date()) {
69
+ const blocks = identifySessionBlocks(entries, 5);
70
+ const nowTime = now.getTime();
71
+ // アクティブブロックを探す(現在時刻がブロックの終了時刻前)
72
+ const activeBlock = blocks.find((b) => nowTime <= b.endTime && nowTime >= b.startTime);
73
+ if (!activeBlock) {
74
+ // アクティブブロックがない場合は0を返す
75
+ return {
76
+ inputTokens: 0,
77
+ outputTokens: 0,
78
+ cacheCreationTokens: 0,
79
+ cacheReadTokens: 0,
80
+ totalTokens: 0,
81
+ blockStartTime: null,
82
+ blockEndTime: null,
83
+ elapsedMinutes: 0,
84
+ remainingMinutes: 0,
85
+ };
86
+ }
87
+ // requestIdで重複除去
88
+ const dedupedEntries = deduplicateByRequestId(activeBlock.entries);
89
+ let inputTokens = 0;
90
+ let outputTokens = 0;
91
+ let cacheCreationTokens = 0;
92
+ let cacheReadTokens = 0;
93
+ for (const entry of dedupedEntries) {
94
+ const usage = entry.message?.usage || entry.usage;
95
+ if (!usage)
96
+ continue;
97
+ inputTokens += usage.input_tokens || 0;
98
+ outputTokens += usage.output_tokens || 0;
99
+ cacheCreationTokens += usage.cache_creation_input_tokens || 0;
100
+ cacheReadTokens += usage.cache_read_input_tokens || 0;
101
+ }
102
+ const totalTokens = calculateTotalTokens(inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens);
103
+ const elapsedMinutes = Math.round((nowTime - activeBlock.startTime) / 60000);
104
+ const remainingMinutes = Math.round((activeBlock.endTime - nowTime) / 60000);
105
+ return {
106
+ inputTokens,
107
+ outputTokens,
108
+ cacheCreationTokens,
109
+ cacheReadTokens,
110
+ totalTokens,
111
+ blockStartTime: new Date(activeBlock.startTime),
112
+ blockEndTime: new Date(activeBlock.endTime),
113
+ elapsedMinutes,
114
+ remainingMinutes,
115
+ };
116
+ }
117
+ // 期間内の使用量を計算(後方互換性のため残す)
118
+ export function calculateUsageForPeriod(entries, hoursAgo, now = new Date()) {
119
+ const cutoff = new Date(now.getTime() - hoursAgo * 60 * 60 * 1000);
120
+ // 期間内のエントリをフィルタリング
121
+ const filteredEntries = entries.filter((entry) => {
122
+ const timestamp = entry.timestamp || entry.message?.timestamp;
123
+ if (!timestamp)
124
+ return false;
125
+ const entryTime = new Date(timestamp);
126
+ return entryTime >= cutoff;
127
+ });
128
+ // requestIdで重複除去
129
+ const dedupedEntries = deduplicateByRequestId(filteredEntries);
130
+ let inputTokens = 0;
131
+ let outputTokens = 0;
132
+ let cacheCreationTokens = 0;
133
+ let cacheReadTokens = 0;
134
+ for (const entry of dedupedEntries) {
135
+ const usage = entry.message?.usage || entry.usage;
136
+ if (!usage)
137
+ continue;
138
+ inputTokens += usage.input_tokens || 0;
139
+ outputTokens += usage.output_tokens || 0;
140
+ cacheCreationTokens += usage.cache_creation_input_tokens || 0;
141
+ cacheReadTokens += usage.cache_read_input_tokens || 0;
142
+ }
143
+ const totalTokens = calculateTotalTokens(inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens);
144
+ return {
145
+ inputTokens,
146
+ outputTokens,
147
+ cacheCreationTokens,
148
+ cacheReadTokens,
149
+ totalTokens,
150
+ };
151
+ }
152
+ const WEEKLY_RESET = { weekday: 6, hour: 22, minute: 59 }; // Saturday 22:59 (local time)
153
+ export function getLastWeeklyReset(now = new Date()) {
154
+ const reset = new Date(now);
155
+ const day = reset.getDay();
156
+ const diff = (day - WEEKLY_RESET.weekday + 7) % 7;
157
+ reset.setDate(reset.getDate() - diff);
158
+ reset.setHours(WEEKLY_RESET.hour, WEEKLY_RESET.minute, 0, 0);
159
+ if (now < reset) {
160
+ reset.setDate(reset.getDate() - 7);
161
+ }
162
+ return reset;
163
+ }
164
+ export function getNextWeeklyReset(now = new Date()) {
165
+ const lastReset = getLastWeeklyReset(now);
166
+ const nextReset = new Date(lastReset);
167
+ nextReset.setDate(nextReset.getDate() + 7);
168
+ return nextReset;
169
+ }
170
+ function calculateUsageSince(entries, startTime, now = new Date()) {
171
+ // 期間内のエントリをフィルタリング
172
+ const filteredEntries = entries.filter((entry) => {
173
+ const timestamp = entry.timestamp || entry.message?.timestamp;
174
+ if (!timestamp)
175
+ return false;
176
+ const entryTime = new Date(timestamp);
177
+ return entryTime >= startTime && entryTime <= now;
178
+ });
179
+ // requestIdで重複除去
180
+ const dedupedEntries = deduplicateByRequestId(filteredEntries);
181
+ let inputTokens = 0;
182
+ let outputTokens = 0;
183
+ let cacheCreationTokens = 0;
184
+ let cacheReadTokens = 0;
185
+ for (const entry of dedupedEntries) {
186
+ const usage = entry.message?.usage || entry.usage;
187
+ if (!usage)
188
+ continue;
189
+ inputTokens += usage.input_tokens || 0;
190
+ outputTokens += usage.output_tokens || 0;
191
+ cacheCreationTokens += usage.cache_creation_input_tokens || 0;
192
+ cacheReadTokens += usage.cache_read_input_tokens || 0;
193
+ }
194
+ const totalTokens = calculateTotalTokens(inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens);
195
+ return {
196
+ inputTokens,
197
+ outputTokens,
198
+ cacheCreationTokens,
199
+ cacheReadTokens,
200
+ totalTokens,
201
+ };
202
+ }
203
+ // 使用量を集計
204
+ export function aggregateUsage(entries, now = new Date()) {
205
+ let totalInputTokens = 0;
206
+ let totalOutputTokens = 0;
207
+ let totalCacheCreationInputTokens = 0;
208
+ let totalCacheReadInputTokens = 0;
209
+ let messageCount = 0;
210
+ const byModel = {};
211
+ const byDate = {};
212
+ // requestIdで重複除去
213
+ const dedupedEntries = deduplicateByRequestId(entries);
214
+ for (const entry of dedupedEntries) {
215
+ const usage = entry.message?.usage || entry.usage;
216
+ if (!usage)
217
+ continue;
218
+ const inputTokens = usage.input_tokens || 0;
219
+ const outputTokens = usage.output_tokens || 0;
220
+ const cacheCreation = usage.cache_creation_input_tokens || 0;
221
+ const cacheRead = usage.cache_read_input_tokens || 0;
222
+ totalInputTokens += inputTokens;
223
+ totalOutputTokens += outputTokens;
224
+ totalCacheCreationInputTokens += cacheCreation;
225
+ totalCacheReadInputTokens += cacheRead;
226
+ messageCount++;
227
+ // モデル別集計
228
+ const model = entry.message?.model || entry.model || 'unknown';
229
+ if (!byModel[model]) {
230
+ byModel[model] = {
231
+ inputTokens: 0,
232
+ outputTokens: 0,
233
+ cacheCreationTokens: 0,
234
+ cacheReadTokens: 0,
235
+ count: 0,
236
+ };
237
+ }
238
+ byModel[model].inputTokens += inputTokens;
239
+ byModel[model].outputTokens += outputTokens;
240
+ byModel[model].cacheCreationTokens += cacheCreation;
241
+ byModel[model].cacheReadTokens += cacheRead;
242
+ byModel[model].count++;
243
+ // 日別集計
244
+ const timestamp = entry.timestamp || entry.message?.timestamp;
245
+ if (timestamp) {
246
+ const date = new Date(timestamp).toISOString().split('T')[0];
247
+ if (!byDate[date]) {
248
+ byDate[date] = {
249
+ inputTokens: 0,
250
+ outputTokens: 0,
251
+ cacheCreationTokens: 0,
252
+ cacheReadTokens: 0,
253
+ count: 0,
254
+ };
255
+ }
256
+ byDate[date].inputTokens += inputTokens;
257
+ byDate[date].outputTokens += outputTokens;
258
+ byDate[date].cacheCreationTokens += cacheCreation;
259
+ byDate[date].cacheReadTokens += cacheRead;
260
+ byDate[date].count++;
261
+ }
262
+ }
263
+ // セッションブロック方式の使用量を計算(Claude Code準拠)
264
+ const activeBlock = calculateActiveBlockUsage(entries, now);
265
+ // ローリングウィンドウの使用量を計算(後方互換性)
266
+ const last5Hours = calculateUsageForPeriod(entries, 5, now);
267
+ const last24Hours = calculateUsageForPeriod(entries, 24, now);
268
+ const lastWeek = calculateUsageSince(entries, getLastWeeklyReset(now), now);
269
+ return {
270
+ summary: {
271
+ totalInputTokens,
272
+ totalOutputTokens,
273
+ totalTokens: totalInputTokens + totalOutputTokens,
274
+ cacheCreationInputTokens: totalCacheCreationInputTokens,
275
+ cacheReadInputTokens: totalCacheReadInputTokens,
276
+ messageCount,
277
+ },
278
+ // セッションブロック(Claude Code準拠)
279
+ activeBlock,
280
+ // ローリングウィンドウ(後方互換性)
281
+ limits: {
282
+ last5Hours,
283
+ last24Hours,
284
+ lastWeek,
285
+ },
286
+ byModel,
287
+ byDate,
288
+ };
289
+ }
290
+ // パーセント計算
291
+ export function percent(used, limit) {
292
+ if (limit <= 0)
293
+ return 0;
294
+ return Math.min(100, Math.max(0, Math.round((used / limit) * 100)));
295
+ }
296
+ // トークン数フォーマット
297
+ export function formatTokens(n) {
298
+ if (n >= 1_000_000)
299
+ return `${(n / 1_000_000).toFixed(1)}M`;
300
+ if (n >= 1_000)
301
+ return `${(n / 1_000).toFixed(0)}K`;
302
+ return n.toString();
303
+ }
304
+ //# sourceMappingURL=calculations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calculations.js","sourceRoot":"","sources":["../src/calculations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { aggregateUsage, calculateActiveBlockUsage, calculateUsageForPeriod } from './calculations.js';
3
+ export { calculateUsageForPeriod, calculateActiveBlockUsage, aggregateUsage };
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAKA,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,uBAAuB,EAKxB,MAAM,mBAAmB,CAAA;AAiQ1B,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,cAAc,EAAE,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,220 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync, readdirSync, statSync, existsSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { homedir } from 'os';
5
+ import { aggregateUsage, calculateActiveBlockUsage, calculateUsageForPeriod, getLastWeeklyReset, getNextWeeklyReset, } from './calculations.js';
6
+ // 設定
7
+ const CLAUDE_DIR = join(homedir(), '.claude');
8
+ const PROJECTS_DIR = join(CLAUDE_DIR, 'projects');
9
+ // コマンドライン引数を解析
10
+ const args = process.argv.slice(2);
11
+ function getArgValue(name) {
12
+ const arg = args.find((a) => a.startsWith(`--${name}=`));
13
+ return arg ? arg.split('=')[1] : null;
14
+ }
15
+ const flags = {
16
+ help: args.includes('--help') || args.includes('-h'),
17
+ json: args.includes('--json'),
18
+ send: args.includes('--send'),
19
+ verbose: args.includes('--verbose') || args.includes('-v'),
20
+ };
21
+ // API URL(環境変数 or コマンドライン引数)
22
+ const API_URL = process.env.SYNC_API_URL || getArgValue('api-url');
23
+ const USER_ID = process.env.SYNC_USER_ID || getArgValue('user-id') || 'msgmacbookair';
24
+ // ヘルプ表示
25
+ if (flags.help) {
26
+ console.log(`
27
+ token-usage-sync - Claude Code使用量をダッシュボードに同期
28
+
29
+ 使い方:
30
+ npx token-usage-sync [オプション]
31
+
32
+ オプション:
33
+ --json JSON形式で出力
34
+ --send ダッシュボードに送信(--api-url必須)
35
+ --api-url=URL 送信先APIのURL
36
+ --user-id=ID ユーザーID(デフォルト: default-user)
37
+ --verbose 詳細ログ出力
38
+ --help このヘルプを表示
39
+
40
+ 環境変数:
41
+ SYNC_API_URL 送信先URL(--api-urlの代わり)
42
+ SYNC_USER_ID ユーザーID(--user-idの代わり)
43
+
44
+ 例:
45
+ # 使用量を表示(ローカルJSONLから計算)
46
+ npx token-usage-sync
47
+
48
+ # ダッシュボードに送信
49
+ npx token-usage-sync --send
50
+
51
+ # JSON形式で出力
52
+ npx token-usage-sync --json
53
+
54
+ 推奨ワークフロー:
55
+ 1. npx ccusage blocks → セッションブロックの詳細を確認
56
+ 2. npx token-usage-sync --send → ダッシュボードに同期
57
+ `);
58
+ process.exit(0);
59
+ }
60
+ // JSONLファイルを再帰的に探す
61
+ function findJsonlFiles(dir, files = []) {
62
+ if (!existsSync(dir))
63
+ return files;
64
+ const entries = readdirSync(dir);
65
+ for (const entry of entries) {
66
+ const fullPath = join(dir, entry);
67
+ const stat = statSync(fullPath);
68
+ if (stat.isDirectory()) {
69
+ findJsonlFiles(fullPath, files);
70
+ }
71
+ else if (entry.endsWith('.jsonl')) {
72
+ files.push(fullPath);
73
+ }
74
+ }
75
+ return files;
76
+ }
77
+ // JSONLファイルを解析
78
+ function parseJsonlFile(filePath) {
79
+ const content = readFileSync(filePath, 'utf-8');
80
+ const lines = content.trim().split('\n').filter((line) => line.trim());
81
+ const entries = [];
82
+ for (const line of lines) {
83
+ try {
84
+ entries.push(JSON.parse(line));
85
+ }
86
+ catch {
87
+ // 無効な行はスキップ
88
+ }
89
+ }
90
+ return entries;
91
+ }
92
+ // メイン処理
93
+ async function main() {
94
+ // ローカルJSONLモード
95
+ // ファイル検索
96
+ if (flags.verbose) {
97
+ console.error(`Searching for JSONL files in: ${PROJECTS_DIR}`);
98
+ }
99
+ const jsonlFiles = findJsonlFiles(PROJECTS_DIR);
100
+ if (jsonlFiles.length === 0) {
101
+ console.error('No JSONL files found in ~/.claude/projects/');
102
+ console.error('Make sure you have used Claude Code at least once.');
103
+ process.exit(1);
104
+ }
105
+ if (flags.verbose) {
106
+ console.error(`Found ${jsonlFiles.length} JSONL files`);
107
+ }
108
+ // 全ファイルを解析
109
+ const allEntries = [];
110
+ for (const file of jsonlFiles) {
111
+ const entries = parseJsonlFile(file);
112
+ allEntries.push(...entries);
113
+ }
114
+ if (flags.verbose) {
115
+ console.error(`Parsed ${allEntries.length} entries`);
116
+ }
117
+ // 集計
118
+ const aggregated = aggregateUsage(allEntries);
119
+ const usage = {
120
+ ...aggregated,
121
+ syncedAt: new Date().toISOString(),
122
+ fileCount: jsonlFiles.length,
123
+ };
124
+ // JSON出力
125
+ if (flags.json) {
126
+ console.log(JSON.stringify(usage, null, 2));
127
+ return;
128
+ }
129
+ // 送信
130
+ if (flags.send) {
131
+ // API URLが指定されていない場合はエラー
132
+ if (!API_URL) {
133
+ console.error('✗ --api-url is required for --send');
134
+ console.error('');
135
+ console.error('Usage:');
136
+ console.error(' npx token-usage-sync --send --api-url=https://your-worker.workers.dev/api/sync-usage');
137
+ console.error('');
138
+ console.error('Or set environment variable:');
139
+ console.error(' export SYNC_API_URL=https://your-worker.workers.dev/api/sync-usage');
140
+ process.exit(1);
141
+ }
142
+ try {
143
+ const response = await fetch(API_URL, {
144
+ method: 'POST',
145
+ headers: {
146
+ 'Content-Type': 'application/json',
147
+ 'X-User-Id': USER_ID,
148
+ },
149
+ body: JSON.stringify(usage),
150
+ });
151
+ if (response.ok) {
152
+ console.log('✓ Usage data synced successfully!');
153
+ const result = (await response.json());
154
+ if (result.dashboardUrl) {
155
+ console.log(` View at: ${result.dashboardUrl}`);
156
+ }
157
+ }
158
+ else {
159
+ console.error(`✗ Failed to sync: ${response.status} ${response.statusText}`);
160
+ process.exit(1);
161
+ }
162
+ }
163
+ catch (e) {
164
+ const error = e;
165
+ console.error(`✗ Failed to sync: ${error.message}`);
166
+ process.exit(1);
167
+ }
168
+ return;
169
+ }
170
+ // デフォルト: 簡易表示
171
+ console.log('\n📊 Claude Code Usage Summary\n');
172
+ // 制限値(Claude.ai UIから逆算: Pro=22.8M)
173
+ const LIMIT_WEEK_RAW = 22_800_000; // 週間制限: 22.8M tokens
174
+ const lastWeekTotal = usage.limits.lastWeek.totalTokens;
175
+ const pctWeek = Math.round((lastWeekTotal / LIMIT_WEEK_RAW) * 100);
176
+ // アクティブブロック(Claude Code準拠のセッションブロック方式)
177
+ console.log('=== Active Session Block ===');
178
+ if (usage.activeBlock && usage.activeBlock.blockStartTime) {
179
+ const elapsed = usage.activeBlock.elapsedMinutes;
180
+ const remaining = usage.activeBlock.remainingMinutes;
181
+ const elapsedStr = `${Math.floor(elapsed / 60)}h ${elapsed % 60}m`;
182
+ const remainingStr = `${Math.floor(remaining / 60)}h ${remaining % 60}m`;
183
+ console.log(`Status: ACTIVE (${elapsedStr} elapsed, ${remainingStr} remaining)`);
184
+ console.log(`Tokens: ${usage.activeBlock.totalTokens.toLocaleString()}`);
185
+ console.log(` Input: ${usage.activeBlock.inputTokens.toLocaleString()}`);
186
+ console.log(` Output: ${usage.activeBlock.outputTokens.toLocaleString()}`);
187
+ console.log(` Cache: ${usage.activeBlock.cacheCreationTokens.toLocaleString()} (create) + ${usage.activeBlock.cacheReadTokens.toLocaleString()} (read)`);
188
+ }
189
+ else {
190
+ console.log('Status: No active block');
191
+ }
192
+ console.log('\n=== Weekly Limit ===');
193
+ const weeklyStart = getLastWeeklyReset();
194
+ const weeklyEnd = getNextWeeklyReset();
195
+ const formatDate = (d) => `${d.getMonth() + 1}/${d.getDate()} ${d.getHours()}:${String(d.getMinutes()).padStart(2, '0')}`;
196
+ console.log(`Period: ${formatDate(weeklyStart)} ~ ${formatDate(weeklyEnd)}`);
197
+ console.log(`Weekly: ${lastWeekTotal.toLocaleString()} / ${LIMIT_WEEK_RAW.toLocaleString()} (${pctWeek}%)`);
198
+ console.log('\n=== All Time Total ===');
199
+ console.log(`Total Tokens: ${usage.summary.totalTokens.toLocaleString()}`);
200
+ console.log(` Input: ${usage.summary.totalInputTokens.toLocaleString()}`);
201
+ console.log(` Output: ${usage.summary.totalOutputTokens.toLocaleString()}`);
202
+ console.log(` Cache (in): ${usage.summary.cacheReadInputTokens.toLocaleString()}`);
203
+ console.log(`Messages: ${usage.summary.messageCount.toLocaleString()}`);
204
+ console.log(`Files: ${usage.fileCount}`);
205
+ if (Object.keys(usage.byModel).length > 0) {
206
+ console.log('\nBy Model:');
207
+ for (const [model, data] of Object.entries(usage.byModel)) {
208
+ const total = data.inputTokens +
209
+ data.outputTokens +
210
+ data.cacheCreationTokens +
211
+ data.cacheReadTokens;
212
+ console.log(` ${model}: ${total.toLocaleString()} tokens`);
213
+ }
214
+ }
215
+ console.log('\n💡 Run with --send to sync to dashboard');
216
+ }
217
+ main().catch(console.error);
218
+ // Re-export for testing
219
+ export { calculateUsageForPeriod, calculateActiveBlockUsage, aggregateUsage };
220
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}