@kaitranntt/ccs 7.77.1-dev.3 → 7.77.1-dev.5

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.
@@ -11,6 +11,38 @@ function normalizeProvider(provider) {
11
11
  }
12
12
  return (0, provider_capabilities_1.mapExternalProviderName)(normalized) ?? normalized;
13
13
  }
14
+ function extractAuthFilenameFromSource(source) {
15
+ const authFileMatch = source.match(/(?:^|\s)auth_file=("[^"]+"|'[^']+'|[^\s]+)/i);
16
+ const rawValue = authFileMatch?.[1] ?? source;
17
+ const value = rawValue.trim().replace(/^['"]|['"]$/g, '');
18
+ const filenameCandidate = value.split('|').pop() ?? value;
19
+ return filenameCandidate.split(/[\\/]/).pop() ?? filenameCandidate.trim();
20
+ }
21
+ function stripKnownAuthPlanSuffix(value) {
22
+ return value.replace(/-(?:free|plus|pro|team|business|enterprise)$/i, '');
23
+ }
24
+ function normalizeAuthFilenameSource(provider, source) {
25
+ const filename = extractAuthFilenameFromSource(source);
26
+ const normalizedProvider = normalizeProvider(provider);
27
+ const hadJsonExtension = /\.json$/i.test(filename);
28
+ let candidate = filename.replace(/\.json$/i, '');
29
+ const providerPrefix = `${normalizedProvider}-`;
30
+ if (candidate.toLowerCase().startsWith(providerPrefix)) {
31
+ candidate = candidate.slice(providerPrefix.length);
32
+ }
33
+ candidate = candidate.replace(/^[a-f0-9]{8}[-_]/i, '');
34
+ if (hadJsonExtension) {
35
+ candidate = stripKnownAuthPlanSuffix(candidate);
36
+ }
37
+ const parts = candidate.split('@');
38
+ if (parts.length < 2) {
39
+ return null;
40
+ }
41
+ const localPart = parts[0]?.trim();
42
+ const domainPart = parts.slice(1).join('@').trim();
43
+ const email = `${localPart}@${domainPart}`;
44
+ return /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email) ? email.toLowerCase() : null;
45
+ }
14
46
  function buildAuthIndexLookup(authFiles) {
15
47
  const lookup = new Map();
16
48
  const duplicateEmailCounts = new Map();
@@ -61,10 +93,30 @@ function resolveSourceForDetail(resolvedProvider, detail, authIndexLookup) {
61
93
  }
62
94
  const source = detail.source?.trim();
63
95
  if (source) {
64
- return source;
96
+ return normalizeAuthFilenameSource(resolvedProvider, source) ?? source;
65
97
  }
66
98
  return resolvedAuthFile?.source ?? 'unknown';
67
99
  }
100
+ function resolveCountWithDetails(aggregateCount, detailCount) {
101
+ if (aggregateCount === undefined) {
102
+ return detailCount;
103
+ }
104
+ return aggregateCount < detailCount ? detailCount : aggregateCount;
105
+ }
106
+ function shouldReplaceLastUsedAt(current, next) {
107
+ if (!next) {
108
+ return false;
109
+ }
110
+ const nextTime = Date.parse(next);
111
+ if (!Number.isFinite(nextTime)) {
112
+ return false;
113
+ }
114
+ if (!current) {
115
+ return true;
116
+ }
117
+ const currentTime = Date.parse(current);
118
+ return !Number.isFinite(currentTime) || nextTime > currentTime;
119
+ }
68
120
  function buildCliproxyStatsFromUsageResponse(data, options = {}) {
69
121
  const usage = data.usage;
70
122
  const requestsByModel = {};
@@ -78,7 +130,7 @@ function buildCliproxyStatsFromUsageResponse(data, options = {}) {
78
130
  let sawAnyDetail = false;
79
131
  if (usage?.apis) {
80
132
  for (const [provider, providerData] of Object.entries(usage.apis)) {
81
- let sawProviderDetail = false;
133
+ let providerDetailCount = 0;
82
134
  if (!providerData.models) {
83
135
  const normalizedProvider = normalizeProvider(provider);
84
136
  requestsByProvider[normalizedProvider] =
@@ -86,13 +138,15 @@ function buildCliproxyStatsFromUsageResponse(data, options = {}) {
86
138
  continue;
87
139
  }
88
140
  for (const [model, modelData] of Object.entries(providerData.models)) {
89
- requestsByModel[model] = modelData.total_requests ?? 0;
141
+ let modelDetailCount = 0;
90
142
  if (!modelData.details) {
143
+ requestsByModel[model] = (requestsByModel[model] ?? 0) + (modelData.total_requests ?? 0);
91
144
  continue;
92
145
  }
93
146
  for (const detail of modelData.details) {
94
147
  sawAnyDetail = true;
95
- sawProviderDetail = true;
148
+ providerDetailCount++;
149
+ modelDetailCount++;
96
150
  const resolvedProvider = resolveProviderForDetail(provider, detail, authIndexLookup);
97
151
  const source = resolveSourceForDetail(resolvedProvider, detail, authIndexLookup);
98
152
  const accountKey = (0, account_stats_key_1.buildQualifiedAccountStatsKey)(resolvedProvider, source);
@@ -117,24 +171,42 @@ function buildCliproxyStatsFromUsageResponse(data, options = {}) {
117
171
  }
118
172
  const tokens = detail.tokens?.total_tokens ?? 0;
119
173
  accountStats[accountKey].totalTokens += tokens;
120
- accountStats[accountKey].lastUsedAt = detail.timestamp;
174
+ if (shouldReplaceLastUsedAt(accountStats[accountKey].lastUsedAt, detail.timestamp)) {
175
+ accountStats[accountKey].lastUsedAt = detail.timestamp;
176
+ }
121
177
  totalInputTokens += detail.tokens?.input_tokens ?? 0;
122
178
  totalOutputTokens += detail.tokens?.output_tokens ?? 0;
123
179
  }
180
+ requestsByModel[model] =
181
+ (requestsByModel[model] ?? 0) +
182
+ resolveCountWithDetails(modelData.total_requests, modelDetailCount);
124
183
  }
125
- if (!sawProviderDetail) {
184
+ const providerTotal = providerData.total_requests ?? 0;
185
+ if (providerDetailCount === 0) {
126
186
  const normalizedProvider = normalizeProvider(provider);
127
187
  requestsByProvider[normalizedProvider] =
128
- (requestsByProvider[normalizedProvider] ?? 0) + (providerData.total_requests ?? 0);
188
+ (requestsByProvider[normalizedProvider] ?? 0) + providerTotal;
189
+ }
190
+ else if (providerTotal > providerDetailCount) {
191
+ const normalizedProvider = normalizeProvider(provider);
192
+ requestsByProvider[normalizedProvider] =
193
+ (requestsByProvider[normalizedProvider] ?? 0) + (providerTotal - providerDetailCount);
129
194
  }
130
195
  }
131
196
  }
197
+ const aggregateFailureCount = usage?.failure_count ?? data.failed_requests;
198
+ const successCount = sawAnyDetail
199
+ ? resolveCountWithDetails(usage?.success_count, totalSuccessCount)
200
+ : (usage?.success_count ?? 0);
201
+ const failureCount = sawAnyDetail
202
+ ? resolveCountWithDetails(aggregateFailureCount, totalFailureCount)
203
+ : (aggregateFailureCount ?? 0);
204
+ const providerTotalRequests = Object.values(requestsByProvider).reduce((total, count) => total + count, 0);
205
+ const totalRequests = Math.max(usage?.total_requests ?? 0, successCount + failureCount, providerTotalRequests);
132
206
  return {
133
- totalRequests: usage?.total_requests ?? 0,
134
- successCount: sawAnyDetail ? totalSuccessCount : (usage?.success_count ?? 0),
135
- failureCount: sawAnyDetail
136
- ? totalFailureCount
137
- : (usage?.failure_count ?? data.failed_requests ?? 0),
207
+ totalRequests,
208
+ successCount,
209
+ failureCount,
138
210
  tokens: {
139
211
  input: totalInputTokens,
140
212
  output: totalOutputTokens,
@@ -143,7 +215,7 @@ function buildCliproxyStatsFromUsageResponse(data, options = {}) {
143
215
  requestsByModel,
144
216
  requestsByProvider,
145
217
  accountStats,
146
- quotaExceededCount: usage?.failure_count ?? data.failed_requests ?? 0,
218
+ quotaExceededCount: failureCount,
147
219
  retryCount: 0,
148
220
  collectedAt: new Date().toISOString(),
149
221
  };
@@ -1 +1 @@
1
- {"version":3,"file":"stats-transformer.js","sourceRoot":"","sources":["../../../src/cliproxy/services/stats-transformer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stats-transformer.js","sourceRoot":"","sources":["../../../src/cliproxy/services/stats-transformer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { CliproxyUsageApiResponse } from './stats-fetcher';
2
+ interface MergeMissingDetailsOptions {
3
+ appendExtraDetails?: boolean;
4
+ }
5
+ export declare function buildUsageResponseFromQueueRecords(records: unknown[]): CliproxyUsageApiResponse;
6
+ export declare function mergeUsageResponses(base: CliproxyUsageApiResponse, incoming: CliproxyUsageApiResponse): CliproxyUsageApiResponse;
7
+ export declare function mergeUsageResponseWithMissingDetails(base: CliproxyUsageApiResponse, incoming: CliproxyUsageApiResponse | null | undefined, options?: MergeMissingDetailsOptions): CliproxyUsageApiResponse;
8
+ export declare function buildUsageResponseFromApiKeyUsage(rawResponse: unknown): CliproxyUsageApiResponse;
9
+ export declare function hasUsageDetails(response: CliproxyUsageApiResponse): boolean;
10
+ export declare function hasUsageTotals(response: CliproxyUsageApiResponse): boolean;
11
+ export {};
12
+ //# sourceMappingURL=usage-compatibility-transformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-compatibility-transformer.d.ts","sourceRoot":"","sources":["../../../src/cliproxy/services/usage-compatibility-transformer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAyB,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAqBvF,UAAU,0BAA0B;IAClC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAyJD,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,wBAAwB,CA6B/F;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,wBAAwB,EAC9B,QAAQ,EAAE,wBAAwB,GACjC,wBAAwB,CAc1B;AAkTD,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,wBAAwB,EAC9B,QAAQ,EAAE,wBAAwB,GAAG,IAAI,GAAG,SAAS,EACrD,OAAO,GAAE,0BAA+B,GACvC,wBAAwB,CA2C1B;AAED,wBAAgB,iCAAiC,CAAC,WAAW,EAAE,OAAO,GAAG,wBAAwB,CA4ChG;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAE3E;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAE1E"}
@@ -0,0 +1,458 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasUsageTotals = exports.hasUsageDetails = exports.buildUsageResponseFromApiKeyUsage = exports.mergeUsageResponseWithMissingDetails = exports.mergeUsageResponses = exports.buildUsageResponseFromQueueRecords = void 0;
4
+ function asRecord(value) {
5
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
6
+ ? value
7
+ : null;
8
+ }
9
+ function asString(value, fallback) {
10
+ return typeof value === 'string' && value.trim() ? value.trim() : fallback;
11
+ }
12
+ function asNumber(value) {
13
+ if (typeof value === 'number' && Number.isFinite(value)) {
14
+ return value;
15
+ }
16
+ if (typeof value === 'string' && value.trim()) {
17
+ const parsed = Number(value);
18
+ return Number.isFinite(parsed) ? parsed : 0;
19
+ }
20
+ return 0;
21
+ }
22
+ function asBoolean(value) {
23
+ return value === true;
24
+ }
25
+ function normalizeTokens(rawTokens) {
26
+ const tokens = asRecord(rawTokens) ?? {};
27
+ const input = asNumber(tokens.input_tokens);
28
+ const output = asNumber(tokens.output_tokens);
29
+ const reasoning = asNumber(tokens.reasoning_tokens);
30
+ const cached = asNumber(tokens.cached_tokens);
31
+ const explicitTotal = asNumber(tokens.total_tokens);
32
+ const total = explicitTotal || input + output + reasoning + cached;
33
+ return {
34
+ input_tokens: input,
35
+ output_tokens: output,
36
+ reasoning_tokens: reasoning,
37
+ cached_tokens: cached,
38
+ total_tokens: total,
39
+ };
40
+ }
41
+ function normalizeQueueRecord(record) {
42
+ const raw = asRecord(record);
43
+ if (!raw) {
44
+ return null;
45
+ }
46
+ const provider = asString(raw.provider, 'unknown');
47
+ const model = asString(raw.model, asString(raw.alias, 'unknown'));
48
+ const source = asString(raw.source, 'unknown');
49
+ const authIndex = typeof raw.auth_index === 'string' || typeof raw.auth_index === 'number'
50
+ ? raw.auth_index
51
+ : source;
52
+ return {
53
+ timestamp: asString(raw.timestamp, new Date().toISOString()),
54
+ provider,
55
+ model,
56
+ alias: asString(raw.alias, model),
57
+ source,
58
+ auth_index: authIndex,
59
+ request_id: asString(raw.request_id, ''),
60
+ tokens: normalizeTokens(raw.tokens),
61
+ failed: asBoolean(raw.failed),
62
+ };
63
+ }
64
+ function ensureProviderBucket(response, provider) {
65
+ const usage = (response.usage ?? (response.usage = { apis: {} }));
66
+ const apis = (usage.apis ?? (usage.apis = {}));
67
+ return (apis[provider] ?? (apis[provider] = { total_requests: 0, total_tokens: 0, models: {} }));
68
+ }
69
+ function ensureModelBucket(providerBucket, model) {
70
+ const models = (providerBucket.models ?? (providerBucket.models = {}));
71
+ return (models[model] ?? (models[model] = { total_requests: 0, total_tokens: 0, details: [] }));
72
+ }
73
+ function addDetail(response, provider, model, detail) {
74
+ const usage = (response.usage ?? (response.usage = { apis: {} }));
75
+ const providerBucket = ensureProviderBucket(response, provider);
76
+ const modelBucket = ensureModelBucket(providerBucket, model);
77
+ const totalTokens = detail.tokens?.total_tokens ?? 0;
78
+ usage.total_requests = (usage.total_requests ?? 0) + 1;
79
+ usage.total_tokens = (usage.total_tokens ?? 0) + totalTokens;
80
+ if (detail.failed) {
81
+ usage.failure_count = (usage.failure_count ?? 0) + 1;
82
+ response.failed_requests = (response.failed_requests ?? 0) + 1;
83
+ }
84
+ else {
85
+ usage.success_count = (usage.success_count ?? 0) + 1;
86
+ }
87
+ providerBucket.total_requests = (providerBucket.total_requests ?? 0) + 1;
88
+ providerBucket.total_tokens = (providerBucket.total_tokens ?? 0) + totalTokens;
89
+ modelBucket.total_requests = (modelBucket.total_requests ?? 0) + 1;
90
+ modelBucket.total_tokens = (modelBucket.total_tokens ?? 0) + totalTokens;
91
+ (modelBucket.details ?? (modelBucket.details = [])).push(detail);
92
+ }
93
+ function createDetailSignature(provider, model, detail) {
94
+ return [
95
+ provider,
96
+ model,
97
+ detail.request_id?.trim() ?? '',
98
+ detail.timestamp,
99
+ detail.source,
100
+ String(detail.auth_index),
101
+ detail.tokens?.input_tokens ?? 0,
102
+ detail.tokens?.output_tokens ?? 0,
103
+ detail.tokens?.reasoning_tokens ?? 0,
104
+ detail.tokens?.cached_tokens ?? 0,
105
+ detail.tokens?.total_tokens ?? 0,
106
+ detail.failed ? '1' : '0',
107
+ ].join('|');
108
+ }
109
+ function collectResponseDetails(response) {
110
+ const entries = [];
111
+ for (const [provider, providerData] of Object.entries(response.usage?.apis ?? {})) {
112
+ for (const [model, modelData] of Object.entries(providerData.models ?? {})) {
113
+ for (const detail of modelData.details ?? []) {
114
+ entries.push({ provider, model, detail });
115
+ }
116
+ }
117
+ }
118
+ return entries;
119
+ }
120
+ function buildUsageResponseFromQueueRecords(records) {
121
+ const response = {
122
+ failed_requests: 0,
123
+ usage: {
124
+ total_requests: 0,
125
+ success_count: 0,
126
+ failure_count: 0,
127
+ total_tokens: 0,
128
+ apis: {},
129
+ },
130
+ };
131
+ for (const rawRecord of records) {
132
+ const record = normalizeQueueRecord(rawRecord);
133
+ if (!record) {
134
+ continue;
135
+ }
136
+ addDetail(response, record.provider ?? 'unknown', record.model ?? 'unknown', {
137
+ timestamp: record.timestamp ?? new Date().toISOString(),
138
+ source: record.source ?? 'unknown',
139
+ auth_index: record.auth_index ?? record.source ?? 'unknown',
140
+ request_id: record.request_id || undefined,
141
+ tokens: normalizeTokens(record.tokens),
142
+ failed: record.failed === true,
143
+ });
144
+ }
145
+ return response;
146
+ }
147
+ exports.buildUsageResponseFromQueueRecords = buildUsageResponseFromQueueRecords;
148
+ function mergeUsageResponses(base, incoming) {
149
+ const merged = buildUsageResponseFromQueueRecords([]);
150
+ const seen = new Set();
151
+ for (const entry of [...collectResponseDetails(base), ...collectResponseDetails(incoming)]) {
152
+ const signature = createDetailSignature(entry.provider, entry.model, entry.detail);
153
+ if (seen.has(signature)) {
154
+ continue;
155
+ }
156
+ seen.add(signature);
157
+ addDetail(merged, entry.provider, entry.model, entry.detail);
158
+ }
159
+ return merged;
160
+ }
161
+ exports.mergeUsageResponses = mergeUsageResponses;
162
+ function cloneUsageResponse(response) {
163
+ return {
164
+ failed_requests: response.failed_requests ?? 0,
165
+ usage: {
166
+ total_requests: response.usage?.total_requests ?? 0,
167
+ success_count: response.usage?.success_count ?? 0,
168
+ failure_count: response.usage?.failure_count ?? 0,
169
+ total_tokens: response.usage?.total_tokens ?? 0,
170
+ apis: Object.fromEntries(Object.entries(response.usage?.apis ?? {}).map(([provider, providerData]) => [
171
+ provider,
172
+ {
173
+ total_requests: providerData.total_requests ?? 0,
174
+ total_tokens: providerData.total_tokens ?? 0,
175
+ models: Object.fromEntries(Object.entries(providerData.models ?? {}).map(([model, modelData]) => [
176
+ model,
177
+ {
178
+ total_requests: modelData.total_requests ?? 0,
179
+ total_tokens: modelData.total_tokens ?? 0,
180
+ details: (modelData.details ?? []).map((detail) => ({
181
+ ...detail,
182
+ tokens: { ...detail.tokens },
183
+ })),
184
+ },
185
+ ])),
186
+ },
187
+ ])),
188
+ },
189
+ };
190
+ }
191
+ function cloneDetail(detail) {
192
+ return {
193
+ ...detail,
194
+ tokens: { ...detail.tokens },
195
+ };
196
+ }
197
+ function createMissingDetailMergeKey(provider, model, detail) {
198
+ return [
199
+ provider,
200
+ model,
201
+ detail.request_id?.trim() ?? '',
202
+ detail.timestamp,
203
+ detail.source?.trim() ?? '',
204
+ String(detail.auth_index ?? '').trim(),
205
+ detail.tokens?.input_tokens ?? 0,
206
+ detail.tokens?.output_tokens ?? 0,
207
+ detail.tokens?.reasoning_tokens ?? 0,
208
+ detail.tokens?.cached_tokens ?? 0,
209
+ detail.tokens?.total_tokens ?? 0,
210
+ detail.failed ? '1' : '0',
211
+ ].join('|');
212
+ }
213
+ function extractDuplicateIdentityValue(value) {
214
+ const authFileMatch = value.match(/(?:^|\s)auth_file=("[^"]+"|'[^']+'|[^\s]+)/i);
215
+ const rawValue = authFileMatch?.[1] ?? value;
216
+ const unquotedValue = rawValue.trim().replace(/^['"]|['"]$/g, '');
217
+ const pipeCandidate = unquotedValue.split('|').pop() ?? unquotedValue;
218
+ return pipeCandidate.split(/[\\/]/).pop() ?? pipeCandidate.trim();
219
+ }
220
+ function stripKnownAuthPlanSuffix(value) {
221
+ return value.replace(/-(?:free|plus|pro|team|business|enterprise)$/i, '');
222
+ }
223
+ function normalizeDuplicateIdentity(provider, value) {
224
+ const rawValue = String(value ?? '').trim();
225
+ if (!rawValue) {
226
+ return '';
227
+ }
228
+ const normalizedProvider = provider.trim().toLowerCase();
229
+ const identityValue = extractDuplicateIdentityValue(rawValue);
230
+ const hadJsonExtension = /\.json$/i.test(identityValue);
231
+ let candidate = identityValue.replace(/\.json$/i, '');
232
+ const providerPrefix = `${normalizedProvider}-`;
233
+ if (candidate.toLowerCase().startsWith(providerPrefix)) {
234
+ candidate = candidate.slice(providerPrefix.length);
235
+ }
236
+ candidate = candidate.replace(/^[a-f0-9]{8}[-_]/i, '').trim();
237
+ if (hadJsonExtension) {
238
+ candidate = stripKnownAuthPlanSuffix(candidate);
239
+ }
240
+ return candidate ? candidate.toLowerCase() : rawValue.toLowerCase();
241
+ }
242
+ function resolveCompleteDetailDuplicateIdentity(provider, detail) {
243
+ return (normalizeDuplicateIdentity(provider, detail.source) ||
244
+ normalizeDuplicateIdentity(provider, detail.auth_index) ||
245
+ 'unknown');
246
+ }
247
+ function createLikelyLogDuplicateKey(provider, model, detail) {
248
+ return [
249
+ provider,
250
+ model,
251
+ resolveCompleteDetailDuplicateIdentity(provider, detail),
252
+ detail.failed ? '1' : '0',
253
+ ].join('|');
254
+ }
255
+ function createRequestIdDuplicateKey(provider, model, detail) {
256
+ const requestId = detail.request_id?.trim();
257
+ return requestId ? [provider, model, requestId, detail.failed ? '1' : '0'].join('|') : '';
258
+ }
259
+ function parseDetailTimestamp(detail) {
260
+ const timestampMs = Date.parse(detail.timestamp);
261
+ return Number.isFinite(timestampMs) ? timestampMs : null;
262
+ }
263
+ const TOKENLESS_LOG_DUPLICATE_WINDOW_MS = 5000;
264
+ function detailHasTokenUsage(detail) {
265
+ return ((detail.tokens?.input_tokens ?? 0) > 0 ||
266
+ (detail.tokens?.output_tokens ?? 0) > 0 ||
267
+ (detail.tokens?.reasoning_tokens ?? 0) > 0 ||
268
+ (detail.tokens?.cached_tokens ?? 0) > 0 ||
269
+ (detail.tokens?.total_tokens ?? 0) > 0);
270
+ }
271
+ function collectDetailMergeKeyCounts(response) {
272
+ const counts = new Map();
273
+ for (const entry of collectResponseDetails(response)) {
274
+ const key = createMissingDetailMergeKey(entry.provider, entry.model, entry.detail);
275
+ counts.set(key, (counts.get(key) ?? 0) + 1);
276
+ }
277
+ return counts;
278
+ }
279
+ function collectLikelyLogDuplicateCandidates(response) {
280
+ const candidates = {
281
+ byRequestId: new Map(),
282
+ byIdentity: new Map(),
283
+ };
284
+ for (const [provider, providerData] of Object.entries(response.usage?.apis ?? {})) {
285
+ for (const [model, modelData] of Object.entries(providerData.models ?? {})) {
286
+ const details = modelData.details ?? [];
287
+ const canUseIdentityWindow = (modelData.total_requests ?? 0) <= details.length;
288
+ for (const detail of details) {
289
+ const requestIdKey = createRequestIdDuplicateKey(provider, model, detail);
290
+ if (requestIdKey) {
291
+ candidates.byRequestId.set(requestIdKey, (candidates.byRequestId.get(requestIdKey) ?? 0) + 1);
292
+ }
293
+ if (!canUseIdentityWindow) {
294
+ continue;
295
+ }
296
+ const timestampMs = parseDetailTimestamp(detail);
297
+ if (timestampMs === null) {
298
+ continue;
299
+ }
300
+ const key = createLikelyLogDuplicateKey(provider, model, detail);
301
+ const timestamps = candidates.byIdentity.get(key) ?? [];
302
+ timestamps.push(timestampMs);
303
+ candidates.byIdentity.set(key, timestamps);
304
+ }
305
+ }
306
+ }
307
+ return candidates;
308
+ }
309
+ function consumeDetailKey(counts, key) {
310
+ const count = counts.get(key) ?? 0;
311
+ if (count <= 0) {
312
+ return false;
313
+ }
314
+ if (count === 1) {
315
+ counts.delete(key);
316
+ }
317
+ else {
318
+ counts.set(key, count - 1);
319
+ }
320
+ return true;
321
+ }
322
+ function consumeCount(counts, key) {
323
+ const count = counts.get(key) ?? 0;
324
+ if (count <= 0) {
325
+ return false;
326
+ }
327
+ if (count === 1) {
328
+ counts.delete(key);
329
+ }
330
+ else {
331
+ counts.set(key, count - 1);
332
+ }
333
+ return true;
334
+ }
335
+ function consumeLikelyLogDuplicateCandidate(candidates, provider, model, detail) {
336
+ if (detailHasTokenUsage(detail)) {
337
+ return false;
338
+ }
339
+ const requestIdKey = createRequestIdDuplicateKey(provider, model, detail);
340
+ if (requestIdKey && consumeCount(candidates.byRequestId, requestIdKey)) {
341
+ return true;
342
+ }
343
+ const timestampMs = parseDetailTimestamp(detail);
344
+ if (timestampMs === null) {
345
+ return false;
346
+ }
347
+ const key = createLikelyLogDuplicateKey(provider, model, detail);
348
+ const timestamps = candidates.byIdentity.get(key) ?? [];
349
+ const index = timestamps.findIndex((candidateTimestampMs) => Math.abs(candidateTimestampMs - timestampMs) <= TOKENLESS_LOG_DUPLICATE_WINDOW_MS);
350
+ if (index === -1) {
351
+ return false;
352
+ }
353
+ timestamps.splice(index, 1);
354
+ if (timestamps.length === 0) {
355
+ candidates.byIdentity.delete(key);
356
+ }
357
+ else {
358
+ candidates.byIdentity.set(key, timestamps);
359
+ }
360
+ return true;
361
+ }
362
+ function countProviderDetails(providerBucket) {
363
+ return Object.values(providerBucket.models ?? {}).reduce((total, modelData) => total + (modelData.details ?? []).length, 0);
364
+ }
365
+ function appendDetailToExistingProvider(merged, provider, model, detail, options) {
366
+ const providerBucket = ensureProviderBucket(merged, provider);
367
+ const shouldFillAggregateOnly = (providerBucket.total_requests ?? 0) > countProviderDetails(providerBucket);
368
+ if (!shouldFillAggregateOnly) {
369
+ if (!options.appendExtraDetails) {
370
+ return;
371
+ }
372
+ addDetail(merged, provider, model, cloneDetail(detail));
373
+ return;
374
+ }
375
+ const modelBucket = ensureModelBucket(providerBucket, model);
376
+ const shouldFillModelAggregateOnly = (modelBucket.total_requests ?? 0) > (modelBucket.details ?? []).length;
377
+ if (!shouldFillModelAggregateOnly) {
378
+ modelBucket.total_requests = (modelBucket.total_requests ?? 0) + 1;
379
+ }
380
+ (modelBucket.details ?? (modelBucket.details = [])).push(cloneDetail(detail));
381
+ }
382
+ function mergeUsageResponseWithMissingDetails(base, incoming, options = {}) {
383
+ if (!incoming || !hasUsageDetails(incoming)) {
384
+ return base;
385
+ }
386
+ const normalizedOptions = {
387
+ appendExtraDetails: options.appendExtraDetails ?? true,
388
+ };
389
+ const merged = cloneUsageResponse(base);
390
+ const existingDetailCounts = collectDetailMergeKeyCounts(base);
391
+ const likelyLogDuplicateCandidates = collectLikelyLogDuplicateCandidates(base);
392
+ for (const entry of collectResponseDetails(incoming)) {
393
+ const mergeKey = createMissingDetailMergeKey(entry.provider, entry.model, entry.detail);
394
+ if (consumeDetailKey(existingDetailCounts, mergeKey)) {
395
+ continue;
396
+ }
397
+ if (consumeLikelyLogDuplicateCandidate(likelyLogDuplicateCandidates, entry.provider, entry.model, entry.detail)) {
398
+ continue;
399
+ }
400
+ if (base.usage?.apis?.[entry.provider]) {
401
+ appendDetailToExistingProvider(merged, entry.provider, entry.model, entry.detail, normalizedOptions);
402
+ continue;
403
+ }
404
+ addDetail(merged, entry.provider, entry.model, cloneDetail(entry.detail));
405
+ }
406
+ return merged;
407
+ }
408
+ exports.mergeUsageResponseWithMissingDetails = mergeUsageResponseWithMissingDetails;
409
+ function buildUsageResponseFromApiKeyUsage(rawResponse) {
410
+ const response = buildUsageResponseFromQueueRecords([]);
411
+ const usage = response.usage ?? {
412
+ total_requests: 0,
413
+ success_count: 0,
414
+ failure_count: 0,
415
+ total_tokens: 0,
416
+ apis: {},
417
+ };
418
+ response.usage = usage;
419
+ const byProvider = asRecord(rawResponse);
420
+ if (!byProvider) {
421
+ return response;
422
+ }
423
+ for (const [provider, sources] of Object.entries(byProvider)) {
424
+ const sourceRecords = asRecord(sources);
425
+ if (!sourceRecords) {
426
+ continue;
427
+ }
428
+ let providerRequests = 0;
429
+ for (const entry of Object.values(sourceRecords)) {
430
+ const usageEntry = asRecord(entry);
431
+ if (!usageEntry) {
432
+ continue;
433
+ }
434
+ const success = asNumber(usageEntry.success);
435
+ const failed = asNumber(usageEntry.failed);
436
+ providerRequests += success + failed;
437
+ usage.success_count = (usage.success_count ?? 0) + success;
438
+ usage.failure_count = (usage.failure_count ?? 0) + failed;
439
+ response.failed_requests = (response.failed_requests ?? 0) + failed;
440
+ }
441
+ if (providerRequests > 0) {
442
+ const providerBucket = ensureProviderBucket(response, provider);
443
+ providerBucket.total_requests = (providerBucket.total_requests ?? 0) + providerRequests;
444
+ usage.total_requests = (usage.total_requests ?? 0) + providerRequests;
445
+ }
446
+ }
447
+ return response;
448
+ }
449
+ exports.buildUsageResponseFromApiKeyUsage = buildUsageResponseFromApiKeyUsage;
450
+ function hasUsageDetails(response) {
451
+ return collectResponseDetails(response).length > 0;
452
+ }
453
+ exports.hasUsageDetails = hasUsageDetails;
454
+ function hasUsageTotals(response) {
455
+ return (response.usage?.total_requests ?? 0) > 0;
456
+ }
457
+ exports.hasUsageTotals = hasUsageTotals;
458
+ //# sourceMappingURL=usage-compatibility-transformer.js.map